@@ -64,10 +64,9 @@ def __init__( # noqa: WPS211
6464 self .dependency_graphs : Dict [str , DependencyGraph ] = {}
6565 self .propagate_exceptions = propagate_exceptions
6666 self .on_exit = on_exit
67+ self .known_tasks : Set [str ] = set ()
6768 for task in self .broker .get_all_tasks ().values ():
68- self .task_signatures [task .task_name ] = inspect .signature (task .original_func )
69- self .task_hints [task .task_name ] = get_type_hints (task .original_func )
70- self .dependency_graphs [task .task_name ] = DependencyGraph (task .original_func )
69+ self ._prepare_task (task .task_name , task .original_func )
7170 self .sem : "Optional[asyncio.Semaphore]" = None
7271 if max_async_tasks is not None and max_async_tasks > 0 :
7372 self .sem = asyncio .Semaphore (max_async_tasks )
@@ -163,7 +162,7 @@ async def callback( # noqa: C901, WPS213, WPS217
163162 if raise_err :
164163 raise exc
165164
166- async def run_task ( # noqa: C901, WPS210
165+ async def run_task ( # noqa: C901, WPS210, WPS213
167166 self ,
168167 target : Callable [..., Any ],
169168 message : TaskiqMessage ,
@@ -190,6 +189,8 @@ async def run_task( # noqa: C901, WPS210
190189 returned = None
191190 found_exception : "Optional[BaseException]" = None
192191 signature = None
192+ if message .task_name not in self .known_tasks :
193+ self ._prepare_task (message .task_name , target )
193194 if self .validate_params :
194195 signature = self .task_signatures .get (message .task_name )
195196 dependency_graph = self .dependency_graphs .get (message .task_name )
@@ -382,3 +383,23 @@ def task_cb(task: "asyncio.Task[Any]") -> None:
382383 # and this behaviour considered to be a Hisenbug.
383384 # https://textual.textualize.io/blog/2023/02/11/the-heisenbug-lurking-in-your-async-code/
384385 task .add_done_callback (task_cb )
386+
387+ def _prepare_task (self , name : str , handler : Callable [..., Any ]) -> None :
388+ """
389+ Prepare task for execution.
390+
391+ This function gets function's signature,
392+ type hints and builds dependency graph.
393+
394+ It's useful for dynamic dependency resolution,
395+ because sometimes the receiver can get
396+ funcion that is defined in runtime. We need
397+ to be aware of that.
398+
399+ :param name: task name.
400+ :param handler: task handler.
401+ """
402+ self .known_tasks .add (name )
403+ self .task_signatures [name ] = inspect .signature (handler )
404+ self .task_hints [name ] = get_type_hints (handler )
405+ self .dependency_graphs [name ] = DependencyGraph (handler )
0 commit comments