44import time
55from concurrent .futures import Future
66from concurrent .futures ._base import PENDING
7- from typing import Optional
7+ from typing import Optional , Tuple
88
99from executorlib .standalone .interactive .communication import (
1010 ExecutorlibSocketError ,
@@ -20,7 +20,7 @@ def execute_task_dict(
2020 cache_directory : Optional [str ] = None ,
2121 cache_key : Optional [str ] = None ,
2222 error_log_file : Optional [str ] = None ,
23- ) -> bool :
23+ ) -> Tuple [ bool , dict ] :
2424 """
2525 Execute the task in the task_dict by communicating it via the interface.
2626
@@ -37,6 +37,7 @@ def execute_task_dict(
3737
3838 Returns:
3939 bool: True if the task was submitted successfully, False otherwise.
40+ dict: Dictionary of nested tasks if any were returned by the executed function, otherwise an empty dictionary.
4041 """
4142 if not future_obj .done () and future_obj .set_running_or_notify_cancel ():
4243 if error_log_file is not None :
@@ -54,7 +55,7 @@ def execute_task_dict(
5455 future_obj = future_obj ,
5556 )
5657 else :
57- return True
58+ return True , {}
5859
5960
6061def task_done (future_queue : queue .Queue ):
@@ -88,7 +89,7 @@ def reset_task_dict(future_obj: Future, future_queue: queue.Queue, task_dict: di
8889
8990def _execute_task_without_cache (
9091 interface : SocketInterface , task_dict : dict , future_obj : Future
91- ) -> bool :
92+ ) -> Tuple [ bool , dict ] :
9293 """
9394 Execute the task in the task_dict by communicating it via the interface.
9495
@@ -101,14 +102,17 @@ def _execute_task_without_cache(
101102 Returns:
102103 bool: True if the task was submitted successfully, False otherwise.
103104 """
105+ new_task_dict = {}
104106 output = interface .send_and_receive_dict (input_dict = task_dict )
105107 if "result" in output :
106108 future_obj .set_result (output ["result" ])
109+ if "tasks_nested" in output :
110+ new_task_dict = output ["tasks_nested" ]
107111 elif isinstance (output ["error" ], ExecutorlibSocketError ):
108- return False
112+ return False , new_task_dict
109113 else :
110114 future_obj .set_exception (exception = output ["error" ])
111- return True
115+ return True , new_task_dict
112116
113117
114118def _execute_task_with_cache (
@@ -117,7 +121,7 @@ def _execute_task_with_cache(
117121 future_obj : Future ,
118122 cache_directory : str ,
119123 cache_key : Optional [str ] = None ,
120- ) -> bool :
124+ ) -> Tuple [ bool , dict ] :
121125 """
122126 Execute the task in the task_dict by communicating it via the interface using the cache in the cache directory.
123127
@@ -139,6 +143,7 @@ def _execute_task_with_cache(
139143 resource_dict = task_dict .get ("resource_dict" , {}),
140144 cache_key = cache_key ,
141145 )
146+ new_task_dict = {}
142147 file_name = os .path .abspath (os .path .join (cache_directory , task_key + "_o.h5" ))
143148 if file_name not in get_cache_files (cache_directory = cache_directory ):
144149 time_start = time .time ()
@@ -148,11 +153,13 @@ def _execute_task_with_cache(
148153 data_dict ["runtime" ] = time .time () - time_start
149154 dump (file_name = file_name , data_dict = data_dict )
150155 future_obj .set_result (output ["result" ])
156+ if "tasks_nested" in output :
157+ new_task_dict = output ["tasks_nested" ]
151158 elif isinstance (output ["error" ], ExecutorlibSocketError ):
152- return False
159+ return False , new_task_dict
153160 else :
154161 future_obj .set_exception (exception = output ["error" ])
155162 else :
156163 _ , _ , result = get_output (file_name = file_name )
157164 future_obj .set_result (result )
158- return True
165+ return True , new_task_dict
0 commit comments