16
16
from pytask import PTask
17
17
from pytask import PythonNode
18
18
from pytask import Session
19
+ from pytask import TaskExecutionStatus
19
20
from pytask import console
20
21
from pytask import get_marks
21
22
from pytask import hookimpl
@@ -52,6 +53,7 @@ def pytask_execute_build(session: Session) -> bool | None: # noqa: C901, PLR091
52
53
__tracebackhide__ = True
53
54
reports = session .execution_reports
54
55
running_tasks : dict [str , Future [Any ]] = {}
56
+ any_coiled_task = any (is_coiled_function (task ) for task in session .tasks )
55
57
56
58
# The executor can only be created after the collection to give users the
57
59
# possibility to inject their own executors.
@@ -66,12 +68,31 @@ def pytask_execute_build(session: Session) -> bool | None: # noqa: C901, PLR091
66
68
while session .scheduler .is_active ():
67
69
try :
68
70
newly_collected_reports = []
69
- ready_tasks = list (session .scheduler .get_ready (10_000 ))
71
+
72
+ # If there is any coiled function, the user probably wants to exploit
73
+ # adaptive scaling. Thus, we need to submit all ready tasks.
74
+ # Unfortunately, all submitted tasks are shown as running although some
75
+ # are pending.
76
+ #
77
+ # Without coiled functions, we submit as many tasks as there are
78
+ # available workers since we cannot reliably detect a pending status.
79
+ #
80
+ # See #98 for more information.
81
+ if any_coiled_task :
82
+ n_new_tasks = 10_000
83
+ else :
84
+ n_new_tasks = session .config ["n_workers" ] - len (running_tasks )
85
+
86
+ ready_tasks = (
87
+ list (session .scheduler .get_ready (n_new_tasks ))
88
+ if n_new_tasks >= 1
89
+ else []
90
+ )
70
91
71
92
for task_name in ready_tasks :
72
93
task = session .dag .nodes [task_name ]["task" ]
73
94
session .hook .pytask_execute_task_log_start (
74
- session = session , task = task
95
+ session = session , task = task , status = TaskExecutionStatus . RUNNING
75
96
)
76
97
try :
77
98
session .hook .pytask_execute_task_setup (
0 commit comments