Skip to content

Fix #4729: composite rebuild must not re-fire member side effects (JasperFx 2.9.13)#4733

Merged
jeremydmiller merged 1 commit into
masterfrom
fix-4729-composite-rebuild-side-effects
Jun 13, 2026
Merged

Fix #4729: composite rebuild must not re-fire member side effects (JasperFx 2.9.13)#4733
jeremydmiller merged 1 commit into
masterfrom
fix-4729-composite-rebuild-side-effects

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Closes #4729.

Problem

A CompositeProjectionFor whose stage member raises side effects (RaiseSideEffectsslice.PublishMessage / slice.AppendEvent) re-fired those side effects on every rebuild, whereas an equivalent standalone SingleStreamProjection rebuild does not (pinned by side_effects_in_aggregations.side_effects_do_not_happen_in_rebuilds). For a member that publishes an external message (invoice/notification), a composite rebuild re-published it every time.

Fix (JasperFx 2.9.13)

This bumps the JasperFx packages 2.9.10 → 2.9.13, which carries the two-part fix:

  • Query Documentationn update #447CompositeReplayExecutor only set the ShardExecutionMode on the parent composite execution; the member executions defaulted to Continuous and were never updated, so the optimized rebuild ran members in Continuous and fired their side effects. CompositeExecution now propagates its Mode to every member, so members run in CatchUp/Rebuild during a rebuild and suppress side effects — matching the classic single-stream path.
  • Document projections on an array field (SelectMany) #448 — a follow-up that decouples slice.Snapshot assignment from side-effect publishing in AggregationRunner. After Query Documentationn update #447, multi-stage composites lost the upstream Updated<TDoc> fan-out during a rebuild (the snapshot was only set on the Continuous path, and downstream stages threw NREs). The snapshot is now set in every mode; only the side effects stay Continuous-only. (2.9.12 shipped Query Documentationn update #447 alone and regressed multi_stage_projections — this PR targets 2.9.13.)

Tests

🤖 Generated with Claude Code

… effects) + regression test

JasperFx 2.9.13 fixes #4729 in two parts:
 - #447: the optimized composite rebuild propagates the composite's ShardExecutionMode
   to its member executions. Members defaulted to ShardExecutionMode.Continuous
   (CompositeReplayExecutor only set the parent's Mode), so a composite rebuild re-fired the
   members' RaiseSideEffects (PublishMessage/AppendEvent) every time — unlike the classic
   single-stream rebuild pinned by side_effects_do_not_happen_in_rebuilds.
 - #448: decouples slice.Snapshot assignment from side-effect publishing in
   AggregationRunner so multi-stage composites still fan the upstream Updated<TDoc> events to
   downstream stages during a rebuild. (#447 alone left the snapshot unset off the Continuous
   path, so downstream stages lost the synthetic events and threw NREs — 2.9.12 is incomplete.)

Adds an end-to-end regression test: a composite whose stage-2 member publishes a side-effect
message must publish during continuous operation but NOT during RebuildProjectionAsync. Also
corrects the now-inaccurate class comment on the #4727 sharded test (side effects are suppressed
during rebuild post-#4729).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller jeremydmiller merged commit 27231c2 into master Jun 13, 2026
8 checks passed
@jeremydmiller jeremydmiller deleted the fix-4729-composite-rebuild-side-effects branch June 13, 2026 14:45
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.

Side effects fire during the optimized composite rebuild (Continuous mode) but are suppressed in classic rebuilds — intended?

1 participant