fix(amber): pass unstamped boundary states through LoopEnd instead of consuming them#6913
Open
aglinxinyuan wants to merge 1 commit into
Open
fix(amber): pass unstamped boundary states through LoopEnd instead of consuming them#6913aglinxinyuan wants to merge 1 commit into
aglinxinyuan wants to merge 1 commit into
Conversation
… consuming them Follow-up to apache#6661 (review discussion r3648708075). A loop-body operator that emits its own boundary state (produce_state_on_start/finish -- a public API on both engine sides) sends it with the "no loop" envelope (counter 0, loop_start_id ""). The LoopEnd matching branch treated EVERY counter-0 frame as the loop's own boundary state: it captured the back-jump id from the frame (clobbering the real id with "") and handed the state to run_update, which expects the loop `table` payload (KeyError). Either way the loop broke with "no loop-back state URI configured for LoopStart ''". A real loop state is always stamped -- the matching LoopStart stamps its own id on every iteration's output state -- so the consumer can key on the stamp: an UNstamped counter-0 frame at a LoopEnd is now forwarded downstream unchanged, skipping the operator, like any default pass-through. The captured back-jump id is untouched. Also adds the comment the review asked for at the two Scala boundary-state emit sites (StartChannelHandler / EndChannelHandler), documenting that their "no loop" envelope defaults are deliberate and what the Python LoopEnd runtime does with them. Tests: a unit test pins the forward/skip/no-clobber behavior for unstamped frames (the stamped-consume test is unchanged), and a new LoopIntegrationSpec e2e case runs a loop whose body is a Python UDF emitting boundary state via produce_state_on_finish -- it crashes without this fix and completes 3 iterations with it.
Contributor
Automated Reviewer SuggestionsBased on the
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6913 +/- ##
============================================
- Coverage 78.70% 78.69% -0.01%
+ Complexity 3740 3738 -2
============================================
Files 1161 1161
Lines 46084 46088 +4
Branches 5110 5110
============================================
+ Hits 36269 36271 +2
- Misses 8206 8207 +1
- Partials 1609 1610 +1
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Contributor
✅ No material benchmark regressions detected🟢 4 better · 🔴 0 worse · ⚪ 11 noise (<±5%) · 0 without baseline
Baseline detailsLatest main
Raw CSVconfig_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,484.32,200,128000,413,0.252,23575.80,30142.89,30142.89
1,100,10,64,20,2463.59,2000,1280000,812,0.495,122024.29,149888.01,149888.01
2,1000,10,64,20,21117.80,20000,12800000,947,0.578,1061712.65,1097831.35,1097831.35 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changes were proposed in this PR?
Follow-up to #6661, addressing this review comment: a loop-body operator that emits its own boundary state (
produce_state_on_start/finish— a public API on both engine sides) sends it with the "no loop" envelope (counter0,loop_start_id ""). The LoopEnd matching branch treated every counter-0 frame as the loop's own boundary state:Consuming the unstamped state (1) clobbers the captured back-jump id with
""→no loop-back state URI configured for LoopStart '', and (2) handsrun_updatea State with notablepayload →KeyError. Either way the loop breaks. The reviewer reasoned this for a stateful JVM operator; it is language-independent (a Python UDF hits the identical path — no JVM built-in currently overridesproduceStateOnFinish, so the Python UDF is also the practical repro).Fix (consumer-side). A real loop state is always stamped — the matching LoopStart stamps its own id on every iteration's output state — so the LoopEnd runtime now keys on the stamp:
loop_start_idset)"")KeyErrorAlso adds the comment the review asked for at the two Scala boundary-state emit sites (
StartChannelHandler/EndChannelHandler), documenting that their "no loop" envelope defaults are deliberate and how the LoopEnd runtime treats them.Any related issues, documentation, discussions?
Follow-up to #6661 (review discussion r3648708075). Related engine context: #6660.
How was this PR tested?
test_main_loop.py): new test pins that an unstamped counter-0 frame at a LoopEnd is forwarded with its envelope unchanged, the operator is not invoked, and the captured back-jump id is not clobbered (red before the fix); the existing stamped-consume test is unchanged and still passing (95/95 across the loop suites locally).LoopIntegrationSpec, CI-only): new case runsTextInput → LoopStart → stateful Python UDF → LoopEndwhere the UDF emits boundary state viaproduce_state_on_finish— it crashes without this fix and completes exactly 3 iterations with it.scalafmtCheckAll+scalafixAll --check+ full test-compile + ruff format/check pass locally (Java 17).Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Fable 5)