Skip to content

add FBOrJoin (WCP-07 Structured Synchronizing Merge) - #76

Merged
noha merged 1 commit into
mainfrom
add-or-join
Jul 16, 2026
Merged

add FBOrJoin (WCP-07 Structured Synchronizing Merge)#76
noha merged 1 commit into
mainfrom
add-or-join

Conversation

@noha

@noha noha commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Key realization while designing this: the actual join-completion logic (wait until arrived size >= expected size, then aggregate and follow outgoing) is identical between AND-Join and OR-Join - the only difference is where expected's size comes from. AND-Join uses the join node's static incoming count; OR-Join needs the count of branches the preceding OR-Split actually started this time, which is only known at runtime.

Renamed FBAndJoinBehavior to the neutral FBJoinBehavior and share it between FBAndJoin and the new FBOrJoin, rather than duplicating the same logic into a separate FBOrJoinBehavior. Safe to rename outright (no compatibility class) since it's a behavior class - transient, never persisted per-instance in Soil, and was only introduced this session (PR #74), same reasoning as the FBJoinNode -> FBParallelJoinNode rename from PR #55. Verified the rename didn't leave stale source text anywhere (Class rename: updates the live binding but not already-compiled callers' decompiled source, so FBAndJoin>>defaultBehaviorClass needed an explicit recompile to actually say FBJoinBehavior in its source, not just resolve correctly at runtime) and re-grepped for lingering references to the old name.

FBMultiChoiceGatewayBehavior (the OR-Split) now generates a splitId, determines which outgoing transitions actually match their condition before following any of them, registers that count via a new FBFlowInstance>>registerExpectedBranchCount:forSplitId:, then assigns each matching branch its own branchId - same pattern as FBAndSplitBehavior from PR #73. FBFlowInstance>>joinStateFor:splitId: now checks for a registered dynamic count first and falls back to the static incoming count (AND-Join's existing, unchanged path) only if none was registered.

Verified with 1-of-2, 2-of-2, and 2-of-3 branch combinations: the join proceeds as soon as the branches actually taken have all arrived, never waiting for a branch whose condition was false and so was never started. Value aggregation (from PR #75) works the same way, containing only the actually-started branches.

138/138 tests passing (134 existing + 4 new in FBOrJoinBehaviorTest). Full sample-flow smoke test unchanged. FBOrJoin inherits the same >=2 incoming / <=1 outgoing arity validation as every other FBMergeGateway subclass, verified directly.

Key realization while designing this: the actual join-completion logic (wait until arrived size >= expected size, then aggregate and follow outgoing) is identical between AND-Join and OR-Join - the only difference is where `expected`'s size comes from. AND-Join uses the join node's static incoming count; OR-Join needs the count of branches the preceding OR-Split *actually started this time*, which is only known at runtime.

Renamed FBAndJoinBehavior to the neutral FBJoinBehavior and share it between FBAndJoin and the new FBOrJoin, rather than duplicating the same logic into a separate FBOrJoinBehavior. Safe to rename outright (no compatibility class) since it's a behavior class - transient, never persisted per-instance in Soil, and was only introduced this session (PR #74), same reasoning as the FBJoinNode -> FBParallelJoinNode rename from PR #55. Verified the rename didn't leave stale source text anywhere (Class rename: updates the live binding but not already-compiled callers' decompiled source, so FBAndJoin>>defaultBehaviorClass needed an explicit recompile to actually say FBJoinBehavior in its source, not just resolve correctly at runtime) and re-grepped for lingering references to the old name.

FBMultiChoiceGatewayBehavior (the OR-Split) now generates a splitId, determines which outgoing transitions actually match their condition *before* following any of them, registers that count via a new FBFlowInstance>>registerExpectedBranchCount:forSplitId:, then assigns each matching branch its own branchId - same pattern as FBAndSplitBehavior from PR #73. FBFlowInstance>>joinStateFor:splitId: now checks for a registered dynamic count first and falls back to the static incoming count (AND-Join's existing, unchanged path) only if none was registered.

Verified with 1-of-2, 2-of-2, and 2-of-3 branch combinations: the join proceeds as soon as the branches actually taken have all arrived, never waiting for a branch whose condition was false and so was never started. Value aggregation (from PR #75) works the same way, containing only the actually-started branches.

138/138 tests passing (134 existing + 4 new in FBOrJoinBehaviorTest). Full sample-flow smoke test unchanged. FBOrJoin inherits the same >=2 incoming / <=1 outgoing arity validation as every other FBMergeGateway subclass, verified directly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@noha
noha merged commit 4503291 into main Jul 16, 2026
3 checks passed
@noha
noha deleted the add-or-join branch July 20, 2026 07:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant