39 lines
2.2 KiB
Diff
39 lines
2.2 KiB
Diff
# UNDF: UNDF-2026-000000159
|
|
--- a/luigi/scheduler.py
|
|
+++ b/luigi/scheduler.py
|
|
@@ -1288,18 +1288,25 @@ class CentralPlannerScheduler(object):
|
|
def _upstream_status(self, task_id, upstream_status_table):
|
|
if task_id in upstream_status_table:
|
|
return upstream_status_table[task_id]
|
|
elif self._state.has_task(task_id):
|
|
task_stack = [task_id]
|
|
+ in_stack = {task_id} # O(1) membership test; prevents duplicate stack entries
|
|
|
|
while task_stack:
|
|
dep_id = task_stack.pop()
|
|
+ in_stack.discard(dep_id)
|
|
dep = self._state.get_task(dep_id)
|
|
if dep:
|
|
if dep.status == DONE:
|
|
continue
|
|
if dep_id not in upstream_status_table:
|
|
if dep.status == PENDING and dep.deps:
|
|
- task_stack += [dep_id] + list(dep.deps)
|
|
- upstream_status_table[dep_id] = "" # will be updated postorder
|
|
+ # re-push dep_id for postorder processing
|
|
+ task_stack.append(dep_id)
|
|
+ in_stack.add(dep_id)
|
|
+ upstream_status_table[dep_id] = "" # will be updated postorder
|
|
+ for child_id in dep.deps:
|
|
+ if child_id not in upstream_status_table and child_id not in in_stack:
|
|
+ task_stack.append(child_id)
|
|
+ in_stack.add(child_id)
|
|
else:
|
|
dep_status = STATUS_TO_UPSTREAM_MAP.get(dep.status, "")
|
|
upstream_status_table[dep_id] = dep_status
|
|
elif upstream_status_table[dep_id] == "" and dep.deps:
|
|
# This is the postorder update step when we set the
|
|
# status based on the previously calculated child elements
|
|
status = max((upstream_status_table.get(a_task_id, "") for a_task_id in dep.deps), key=UPSTREAM_SEVERITY_KEY)
|
|
upstream_status_table[dep_id] = status
|
|
return upstream_status_table[dep_id]
|