Execute an action with a timeout to prevent hanging. Uses direct threading instead of ThreadPoolExecutor to avoid executor shutdown issues. Args: action_callable: Callable that executes the action timeout: Maximum execution time in seconds
(self, action_callable, timeout, action_name="unknown")
| 169 | return status |
| 170 | |
| 171 | def _execute_with_timeout(self, action_callable, timeout, action_name="unknown"): |
| 172 | """ |
| 173 | Execute an action with a timeout to prevent hanging. |
| 174 | Uses direct threading instead of ThreadPoolExecutor to avoid executor shutdown issues. |
| 175 | |
| 176 | Args: |
| 177 | action_callable: Callable that executes the action |
| 178 | timeout: Maximum execution time in seconds |
| 179 | action_name: Name of the action for logging |
| 180 | |
| 181 | Returns: |
| 182 | str: 'success', 'failed', or 'timeout' |
| 183 | """ |
| 184 | result_container = {'result': None, 'exception': None, 'completed': False} |
| 185 | |
| 186 | def run_action(): |
| 187 | try: |
| 188 | result_container['result'] = action_callable() |
| 189 | result_container['completed'] = True |
| 190 | except Exception as e: |
| 191 | result_container['exception'] = e |
| 192 | result_container['completed'] = True |
| 193 | |
| 194 | # Run action in separate thread |
| 195 | action_thread = threading.Thread(target=run_action, name=f"Action_{action_name}") |
| 196 | action_thread.daemon = True |
| 197 | action_thread.start() |
| 198 | |
| 199 | # Wait for completion with timeout |
| 200 | action_thread.join(timeout=timeout) |
| 201 | |
| 202 | if not result_container['completed']: |
| 203 | logger.error(f"Action {action_name} timed out after {timeout} seconds") |
| 204 | return 'timeout' |
| 205 | |
| 206 | if result_container['exception']: |
| 207 | logger.error(f"Action {action_name} raised exception: {result_container['exception']}") |
| 208 | return 'failed' |
| 209 | |
| 210 | return result_container['result'] if result_container['result'] else 'failed' |
| 211 | |
| 212 | def load_actions(self): |
| 213 | """Load all actions from the actions file""" |
no test coverage detected