Skip to content

Java SDK: Add edge labels to native Dags - #74523

Open
FrankYang0529 wants to merge 2 commits into
apache:mainfrom
FrankYang0529:java-sdk-edge-label
Open

FrankYang0529 wants to merge 2 commits into
apache:mainfrom
FrankYang0529:java-sdk-edge-label

Conversation

@FrankYang0529

Copy link
Copy Markdown
Member
  • Deps.Flow.label(flow, text) wraps one end of an edge. Each edge of a fan-out can then carry its own label. Declaring an existing edge again only adds the label to that edge.
  • A later label on the same edge replaces the earlier label.

Was generative AI tooling used to co-author this PR?
  • Yes - Claude Code

@jason810496 jason810496 left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks.

I pushed 255a2b1 on top with a few fixes from review:

  • Labels are now applied in the order they were set, so the label set last wins, as in Python's DAG.set_edge_info. Before, a task edge's own label always beat its group edge's label, and relabeling an existing
    group edge didn't take effect.
  • Updated EdgeLabelTest to match. I checked both cases against Python's Label, and the edge_info matches.
  • Corrected the KDoc and docs note: Python's Label also changes the edge when one end is in no task group.

@uranusjr

Copy link
Copy Markdown
Member

Python uses the >> Label >> syntax because this naturally reads like having a label in the arrow. This does not read as well in other languages without >>, and makes even less sense with before.

I think we should come up with a better syntax instead just copying Python with >> and << substituted.

@jason810496 jason810496 left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should come up with a better syntax instead just copying Python with >> and << substituted.

I considered the following syntax before:

loaded.before(reportEmpty, "when empty");
cleaned.after(loaded, "always");

However, the wiring should supports fan-in and fan-out.

loaded.before(reportEmpty, "when empty", reportSuspicious, "when suspicious"); // this is not a working syntax to support fan-in.
// the only sutiable way might looks like:
loaded.before([reportEmpty, reportSuspicious], ["when empty", "when suspicious"]); 
loaded.before([reportEmpty,"when empty"], [reportSuspicious,, "when suspicious"]); 

This is why the current syntax goes with current shape, having a dedicated Flow.label wrapper to representing the edge with label:

loaded.before(Flow.label(reportEmpty, "when empty"), Flow.label(reportSuspicious, "when suspicious"));
cleaned.after(Flow.label(loaded, "always"));

The Go-SDK went with the same shape already and there was't objection back then.
I don't have a better user interface design at this moment.

FrankYang0529 and others added 2 commits October 13, 2026 21:26
Signed-off-by: PoAn Yang <payang@apache.org>
A task edge's own label always won over a group edge's label, and a
relabeled group edge kept its first position, so edge_info differed from
Python's, where the label set last wins. Also note that Python's Label
rewrites an edge when one end is in no task group.

Co-Authored-By: Claude <noreply@anthropic.com>
@FrankYang0529

Copy link
Copy Markdown
Member Author

Thanks for the comments and suggestions.

I agree with Jason that Java checks every varargs argument against the same type. A before(Object...) signature would accept the call above, but it would also accept nodes and labels in any order. Only a runtime check could then catch a misplaced label.

With each label still paired with its node, two changes may make the Java code read better. WDYT?

  1. Add a labeled method to the node so that each call reads more like an arrow with a label on it:

    loaded.before(reportEmpty.labeled("when empty"), reportSuspicious.labeled("when suspicious"));
    cleaned.after(loaded.labeled("always"));

A bad part is that labeled becomes a reserved name for task methods inside a task group, because the generated view of a group inherits every method of the node type.

  1. Let Then, Else and Case take a label directly, because labels are used most often on branches:

    dag.If(HasRows.class).Then(load, "rows found").Else(reportEmpty, "no rows");
    dag.Switch(PickPath.class).Case(handleLong, "long").Case(handleShort, "short");

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants