Skip to content

[Prism] Support injecting triggered bundle for a batch of elements. - #36219

Merged
shunping merged 8 commits into
apache:masterfrom
shunping:prism-trigger-bundle-in-batch
Sep 22, 2025
Merged

[Prism] Support injecting triggered bundle for a batch of elements.#36219
shunping merged 8 commits into
apache:masterfrom
shunping:prism-trigger-bundle-in-batch

Conversation

@shunping

@shunping shunping commented Sep 20, 2025

Copy link
Copy Markdown
Collaborator

Previously, Prism's streaming-first design checked trigger criteria for each element and triggered bundles immediately. This resulted in behavior that diverged from the Dataflow and FnApi runners in batch mode.

To address this, this PR introduces the ability to process and inject triggered bundles in batches, a behavior toggled by the --streaming pipeline option.


However, this change has surfaced issues with unsafe triggers, leading to two failing tests after re-enabling prism on pipelines with unsafe triggers.

  • apache_beam.transforms.trigger_test.TriggerPipelineTest testMethod=test_after_count.

    • Error message:
    apache_beam.testing.util.BeamAssertException: Failed assert: [('A-5', {1, 2, 3, 4, 5}), ('B-4', {8, 9, 6, 7}), ('B-3', {16, 10, 15})] == [('B-4', {8, 9, 6, 7}), ('A-5', {1, 2, 3, 4, 5}), ('B-3', {16, 10, 15}), ('A-2', {10, 11})], 
    unexpected elements [('A-2', {10, 11})]
    
  • apache_beam/examples/complete/game/leader_board_test.py LeaderBoardTest.test_leader_board_users

    • Error message:
    apache_beam.testing.util.BeamAssertException: Failed assert: [] == [('user2_team2', 2), ('user3_team3', 8), ('user4_team3', 5), ('user1_team1', 50)], 
    unexpected elements [('user2_team2', 2), ('user3_team3', 8), ('user4_team3', 5), ('user1_team1', 50)]
    

The two test failures are caused by differences in the window "closing behavior," which determines if a final pane is emitted when a window expires.

message ClosingBehavior {
enum Enum {
UNSPECIFIED = 0;
// Emit output when a window expires, whether or not there has been
// any new data since the last output.
EMIT_ALWAYS = 1;
// Only emit output when new data has arrives since the last output
EMIT_IF_NONEMPTY = 2;
}

The Python SDK defaults to EMIT_ALWAYS, with a TODO to support EMIT_IF_NONEMPTY.

# TODO(robertwb): Support EMIT_IF_NONEMPTY
closing_behavior=beam_runner_api_pb2.ClosingBehavior.EMIT_ALWAYS,

This PR's changes try to align Prism's output with the Dataflow runner's behavior, and I believe the two failing tests will need to be re-benchmarked.

image image

@shunping shunping changed the title Support injecting trigger bundle for a batch of elements. [Prism] Support injecting trigger bundle for a batch of elements. Sep 20, 2025
@codecov

codecov Bot commented Sep 20, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.16393% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 36.12%. Comparing base (bcc8961) to head (bc648d5).
⚠️ Report is 8 commits behind head on master.

Files with missing lines Patch % Lines
...am/runners/prism/internal/engine/elementmanager.go 94.33% 2 Missing and 1 partial ⚠️
sdks/go/pkg/beam/runners/prism/internal/execute.go 62.50% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master   #36219      +/-   ##
============================================
+ Coverage     36.09%   36.12%   +0.02%     
  Complexity     1618     1618              
============================================
  Files          1057     1057              
  Lines        164358   164415      +57     
  Branches       1165     1165              
============================================
+ Hits          59331    59388      +57     
- Misses       102871   102874       +3     
+ Partials       2156     2153       -3     
Flag Coverage Δ
go 28.28% <90.16%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@shunping shunping changed the title [Prism] Support injecting trigger bundle for a batch of elements. [Prism] Support injecting triggered bundle for a batch of elements. Sep 20, 2025
@shunping
shunping force-pushed the prism-trigger-bundle-in-batch branch from fb51d27 to 3e1d66e Compare September 20, 2025 04:46
@github-actions github-actions Bot removed the examples label Sep 20, 2025
@shunping
shunping force-pushed the prism-trigger-bundle-in-batch branch from 3e1d66e to bc648d5 Compare September 20, 2025 12:41
@shunping

shunping commented Sep 20, 2025

Copy link
Copy Markdown
Collaborator Author

The test apache_beam/examples/complete/game/leader_board_test.py::LeaderBoardTest::test_leader_board_users were run in two different workflows:

ERROR    apache_beam.runners.direct.direct_runner:direct_runner.py:148 PrismRunnerSupportVisotr returnsTrue
ERROR    apache_beam.runners.direct.direct_runner:direct_runner.py:218 Running pipeline with PrismRunner.
ERROR    apache_beam.runners.direct.direct_runner:direct_runner.py:237 Exception with PrismRunner:
 [Errno 2] No such file or directory: 'go'

ERROR    apache_beam.runners.direct.direct_runner:direct_runner.py:238 Falling back to DirectRunner
ERROR    apache_beam.runners.direct.direct_runner:direct_runner.py:244 Running pipeline with FnApiRunner.

Looks like we need to install go in that workflow.

@shunping

Copy link
Copy Markdown
Collaborator Author

I am not able to re-enable the pipelines with unsafe triggers to run on prism.

When things are resolved, we can pick up the commit to re-enable and rebenchmark: bc648d5.

@github-actions github-actions Bot removed the examples label Sep 21, 2025
@shunping
shunping force-pushed the prism-trigger-bundle-in-batch branch from 1e91a85 to a62e312 Compare September 21, 2025 01:50
@shunping
shunping marked this pull request as ready for review September 21, 2025 04:27
@github-actions

Copy link
Copy Markdown
Contributor

Assigning reviewers:

R: @jrmccluskey for label python.
R: @lostluck for label go.

Note: If you would like to opt out of this review, comment assign to next reviewer.

Available commands:

  • stop reviewer notifications - opt out of the automated review tooling
  • remind me after tests pass - tag the comment author after tests pass
  • waiting on author - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)

The PR bot will only process comments in the main thread (not review comments).

@lostluck lostluck left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

func (ss *stageState) buildTriggeredBundle(em *ElementManager, key []byte, win typex.Window) int {
func (ss *stageState) buildTriggeredBundle(em *ElementManager, key string, win typex.Window) int {
var toProcess []element
dnt := ss.pendingByKeys[string(key)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'll note that Go does some magic when passing a string cast []byte as a map key inline, which avoids allocating. That's why this method took in a []byte for the key, instead of eagerly converting it.

func() string { return rb.BundleID },
toProcess,
ss.input,
singleSet(string(key)),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

But this over here probably made the string(key) (when key is []byte) moot anyway.

@shunping
shunping merged commit 990b5ff into apache:master Sep 22, 2025
108 of 109 checks passed
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.

2 participants