Coverage for src / moai_adk / core / performance / parallel_processor.py: 0.00%
46 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-20 20:52 +0900
« prev ^ index » next coverage.py v7.12.0, created at 2025-11-20 20:52 +0900
1"""
2Parallel Processing Core
4Provides efficient parallel processing capabilities for concurrent task execution.
5"""
7import asyncio
8from typing import Any, Callable, Coroutine, Dict, List, Optional, Union
11class ParallelProcessor:
12 """
13 A parallel processor for executing tasks concurrently with configurable limits.
15 This class provides a high-level interface for running multiple async tasks
16 in parallel with optional progress tracking and error handling.
17 """
19 def __init__(self, max_workers: Optional[int] = None):
20 """
21 Initialize the parallel processor.
23 Args:
24 max_workers: Maximum number of concurrent tasks. If None, defaults to CPU count.
25 """
26 self.max_workers = max_workers
28 async def process_tasks(
29 self,
30 tasks: List[Callable],
31 progress_callback: Optional[Callable[[int, int], None]] = None,
32 ) -> List[Dict[str, Any]]:
33 """
34 Process multiple tasks concurrently.
36 Args:
37 tasks: List of async task functions or coroutines to execute
38 progress_callback: Optional callback for progress updates (completed, total)
40 Returns:
41 List of results from all completed tasks in the same order as input
43 Raises:
44 Exception: If any task raises an exception
45 """
46 if not tasks:
47 return []
49 results = []
50 completed_count = 0
52 # Validate input
53 self._validate_tasks(tasks)
55 # Initialize progress tracking
56 self._update_progress(progress_callback, completed_count, len(tasks))
58 # Process tasks concurrently
59 for task in tasks:
60 try:
61 # Get coroutine from task
62 coroutine = self._get_coroutine(task)
64 # Execute the task and get result
65 result = await coroutine
66 results.append(result)
67 completed_count += 1
69 # Update progress
70 self._update_progress(progress_callback, completed_count, len(tasks))
72 except Exception as e:
73 # Add context to the exception
74 raise type(e)(f"Task failed: {str(e)}") from e
76 return results
78 def _validate_tasks(self, tasks: List[Callable]) -> None:
79 """Validate that all tasks are callable or coroutines."""
80 if not isinstance(tasks, list):
81 raise TypeError("tasks must be a list")
83 for i, task in enumerate(tasks):
84 if not callable(task) and not asyncio.iscoroutine(task):
85 raise TypeError(f"Task at index {i} is not callable or a coroutine")
87 def _get_coroutine(self, task: Union[Callable, Coroutine]) -> Coroutine:
88 """Extract coroutine from task function or return coroutine directly."""
89 if asyncio.iscoroutine(task):
90 return task
92 if callable(task):
93 try:
94 result = task()
95 if asyncio.iscoroutine(result):
96 return result
97 else:
98 raise TypeError("Task function must return a coroutine")
99 except Exception as e:
100 raise TypeError(f"Failed to execute task function: {str(e)}")
102 raise TypeError(f"Task must be callable or a coroutine, got {type(task)}")
104 def _update_progress(
105 self,
106 progress_callback: Optional[Callable[[int, int], None]],
107 completed: int,
108 total: int,
109 ) -> None:
110 """Update progress callback if provided."""
111 if progress_callback is not None:
112 try:
113 progress_callback(completed, total)
114 except Exception as e:
115 # Log progress callback error but don't fail the entire process
116 print(f"Warning: Progress callback failed: {str(e)}")