Skip to content

link_is_required: stay required when target cannot bypass optional links - #518

Closed
olofsvensson wants to merge 4 commits into
mainfrom
517-links-downstream-of-an-optional-link-stay-required-when-the-target-cant-run-without-them
Closed

olofsvensson wants to merge 4 commits into
mainfrom
517-links-downstream-of-an-optional-link-stay-required-when-the-target-cant-run-without-them

Conversation

@olofsvensson

@olofsvensson olofsvensson commented Oct 21, 2026 •

Copy link
Copy Markdown

Previously, any link whose source had an optional (conditional or explicitly optional) link upstream became optional by default. As a result, unconditional branches that fan out and merge again after a conditional link no longer synchronized at the merge node (ewoksppf 23).

Now such a link is optional only if its target can be reached from the start nodes without going through one of the optional links upstream of the source. Otherwise the target can only run when the source runs, so the link stays required. Graphs without start nodes keep the old, conservative behaviour.

Links inside conditional or error-handler branches are now required. Links from such branches into a merge node are still optional.

Created with the help of claude opus 5.5.

Previously, any link whose source had an optional (conditional or
explicitly optional) link upstream became optional by default. As a
result, unconditional branches that fan out and merge again after a
conditional link no longer synchronized at the merge node (ewoksppf #23).

Now such a link is optional only if its target can be reached from the
start nodes without going through one of the optional links upstream of
the source. Otherwise the target can only run when the source runs, so
the link stays required. Graphs without start nodes keep the old,
conservative behaviour.

Links inside conditional or error-handler branches are now required.
Links from such branches into a merge node are still optional.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.19048% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/ewokscore/graph/analysis.py 96.07% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

@woutdenolf

Copy link
Copy Markdown
Member

Regression: an error-handler branch that merges back into the normal path, downstream of a conditional link

graph LR
  start0 -- "a == 1" --> start
  start --> A
  A --> s
  A -. on_error .-> E
  s --> t
  E --> t
Loading

With a == 1 true and A raising, ewoksppf gives:

  • main: s -> t is optional, so t runs after E.
  • This PR: s -> t is required, so t waits for s. s never runs, so t never runs.
  • Without start0, t already never runs on main. This PR extends that bug to graphs with a conditional link upstream.

@woutdenolf

Copy link
Copy Markdown
Member

Also this PR makes loading MXPressE much slower. I'm wondering whether I should immediately finish #490 or we post-pone ewoks-kit/ewoksppf#23 for the next release.

@woutdenolf

woutdenolf commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

My recommendation: leave #518 out of 5.1.0 and postpone ewoks-kit/ewoksppf#23 to the release that includes #490.

Mostly because loading MXPressE goes much slower with #518 and it introduces a regression.

…of-an-optional-link-stay-required-when-the-target-cant-run-without-them
Keep downstream links optional when an upstream error handler can reach
the merge target, and reuse graph analysis during validation to reduce
repeated reachability work.
@olofsvensson

Copy link
Copy Markdown
Author

I tested to ask claude to fix both issues (test workflow and slowness), and it claims to have done so. Please recheck.

@olofsvensson

Copy link
Copy Markdown
Author

I got a strange error from the CI:

This job failed before it even started running the project tests.

The root cause is in the setup step:

The workflow requests Python 3.8 via actions/setup-python
It runs on ubuntu-latest
On this runner, ubuntu-latest resolves to Ubuntu 26.04
The actions/python-versions manifest does not provide Python 3.8 for Ubuntu 26.04

The log shows:

Version 3.8 was not found in the local cache
The version '3.8' with architecture 'x64' was not found for Ubuntu 26.04.

So the failure is not a test failure in your code; it is an environment/setup failure. The workflow stopped at the Python installation step, so no tests ran.

Likely fix:

Pin the job to an older Ubuntu image that still supports Python 3.8, e.g. ubuntu-22.04
Or update the project to a supported Python version for the current runner

Maybe time to remove Python 3.8 from supported versions?

@woutdenolf

Copy link
Copy Markdown
Member

Suggestion: close this PR in favour of #490 + ewoks-kit/ewoksppf#182.

This PR does not fix either problem:

  • Slow loading: MXPressE setup in ewoksppf takes 2.06 s, against 0.29 s on main. Every link_is_required call builds a new _LinkRequirementAnalysis, and ewoksppf calls it once per link.
  • Error-handler regression: still there, only hidden by the extra link_has_on_error check. In the graph of my earlier comment, when A fails, t only runs if a conditional link like start0 -> start exists upstream. The new test expects t to wait forever when there is none.

_LinkRequirementAnalysis is a step towards what #490 already does: one cached analysis per graph (TaskGraph.analysis).

#490 with ewoks-kit/ewoksppf#182 fixes both problems:

One thing left for ewoks-kit/ewoksppf#191: its test imports the deprecated ewokscore.graph.analysis, which fails under -W error. Use taskgraph.analysis.link_is_required(source, target) instead, as test_ppf_workflow27.py now does in ewoks-kit/ewoksppf#182.

@olofsvensson

Copy link
Copy Markdown
Author

Ok, I agree, let's close this PR and wait for #490.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Links downstream of an optional link stay required when the target can't run without them

2 participants