novatechflow commented on code in PR #662:
URL: https://github.com/apache/wayang/pull/662#discussion_r2711765367


##########
wayang-commons/wayang-core/src/main/java/org/apache/wayang/core/optimizer/enumeration/PlanImplementation.java:
##########
@@ -976,6 +992,67 @@ Stream<ExecutionOperator> streamOperators() {
         return operatorStream;
     }
 
+    /**
+     * Provides a deterministic identifier that captures the current state of 
this plan. While not guaranteed to
+     * be unique, it is stable across runs for the same logical plan and can 
therefore be used for reproducible
+     * ordering.
+     *
+     * @return the deterministic identifier
+     */
+    public String getDeterministicIdentifier() {
+        final String operatorDescriptor = this.operators.stream()
+                .map(PlanImplementation::describeOperator)
+                .sorted()
+                .collect(Collectors.joining("|"));
+        final String junctionDescriptor = this.junctions.values().stream()
+                .map(PlanImplementation::describeJunction)
+                .sorted()
+                .collect(Collectors.joining("|"));
+        final String loopDescriptor = 
this.loopImplementations.entrySet().stream()
+                .map(entry -> describeLoop(entry.getKey(), entry.getValue()))
+                .sorted()
+                .collect(Collectors.joining("|"));
+        return operatorDescriptor + "#" + junctionDescriptor + "#" + 
loopDescriptor;
+    }
+
+    private static String describeOperator(Operator operator) {
+        final String name = operator.getName() == null ? "" : 
operator.getName();
+        return operator.getClass().getName() + ":" + name + ":" + 
operator.getEpoch();
+    }
+
+    private static String describeJunction(Junction junction) {
+        final String source = describeOutputSlot(junction.getSourceOutput());
+        final String targets = IntStream.range(0, junction.getNumTargets())
+                .mapToObj(i -> describeInputSlot(junction.getTargetInput(i)))
+                .sorted()
+                .collect(Collectors.joining(","));
+        return source + "->" + targets;
+    }
+
+    private static String describeLoop(LoopSubplan loop, LoopImplementation 
implementation) {
+        final String descriptor = describeOperator(loop);
+        final String iterationDescriptor = 
implementation.getIterationImplementations().stream()
+                .map(iteration -> 
Integer.toString(iteration.getNumIterations()))
+                .collect(Collectors.joining(","));
+        return descriptor + ":" + iterationDescriptor;
+    }
+
+    private static String describeInputSlot(InputSlot<?> slot) {
+        if (slot == null) {
+            return "null";

Review Comment:
   Returning a "real" `null` would break the deterministic identifier: the 
values are `.sorted()` and then joined, and `sorted()` throws on nulls. The 
literal `"null"` keeps it stable and safe for comparison/concatenation. We 
could switch to real nulls only if we add null-safe sorting/joining.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to