|
5 | 5 | import time |
6 | 6 | import typing |
7 | 7 |
|
| 8 | +import deepmerge |
8 | 9 | from loguru import logger |
9 | 10 | from pydantic.dataclasses import dataclass as pydantic_dataclass |
10 | 11 |
|
|
19 | 20 |
|
20 | 21 | last_run_id: int = 0 |
21 | 22 | partial_result_sender: partial_result_sender_module.PartialResultSender |
22 | | - |
| 23 | +handler_config_merger = deepmerge.Merger( |
| 24 | + [ |
| 25 | + (list, ["override"]), |
| 26 | + (dict, ["merge"]), |
| 27 | + (set, ["override"]) |
| 28 | + ], |
| 29 | + # all other types: |
| 30 | + ["override"], |
| 31 | + # strategies in the case where the types conflict: |
| 32 | + ["override"] |
| 33 | +) |
23 | 34 |
|
24 | 35 | class ActionFailedException(Exception): |
25 | 36 | def __init__(self, message: str) -> None: |
@@ -401,10 +412,14 @@ async def execute_action_handler( |
401 | 412 | handler.source, None |
402 | 413 | ) |
403 | 414 | handler_raw_config = {} |
404 | | - # TODO: deep merge instead? |
405 | 415 | if handler_global_config is not None: |
406 | | - handler_raw_config.update(handler_global_config) |
407 | | - handler_raw_config.update(handler.config) |
| 416 | + handler_raw_config = handler_global_config |
| 417 | + if handler_raw_config == {}: |
| 418 | + # still empty, just assign |
| 419 | + handler_raw_config = handler.config |
| 420 | + else: |
| 421 | + # not empty anymore, deep merge |
| 422 | + handler_config_merger.merge(handler_raw_config, handler.config) |
408 | 423 |
|
409 | 424 | def get_handler_config(param_type): |
410 | 425 | # TODO: validation errors |
@@ -564,6 +579,7 @@ async def run_subresult_coros_sequentially( |
564 | 579 | try: |
565 | 580 | coro_result = await coro |
566 | 581 | except Exception as e: |
| 582 | + logger.error(f"Unhandled exception in subresult coroutine({action_name}, run {run_id}):") |
567 | 583 | logger.exception(e) |
568 | 584 | raise ActionFailedException( |
569 | 585 | f"Running action handlers of '{action_name}' failed(Run {run_id}): {e}" |
|
0 commit comments