Skip to content

Adopt JasperFx 2.39.2 - #5187

Merged
jeremydmiller merged 1 commit into
masterfrom
chore/jasperfx-2.39.2
Aug 4, 2026
Merged

Adopt JasperFx 2.39.2#5187
jeremydmiller merged 1 commit into
masterfrom
chore/jasperfx-2.39.2

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Companion bump for #5186. jasperfx#630.

The contract is now explicit. IEventDatabase.WriteExtendedProgressionAsync(IReadOnlyList<ShardState>, …) previously asked for "as few round-trips as the store can manage — ideally one" and said nothing about transaction scope, which is exactly what made a single UPDATE … FROM unnest(…) a reasonable reading of it. It now states that one row per transaction is required, that what a batch amortizes is the connection (#553's actual concern — N single-row statements on one rented connection still cost one rent), and that implementations should skip rows whose telemetry is unchanged. Polecat needs this before it implements the batched overload.

Batches flush ordered by shard name. With one row per transaction a single writer never holds more than one row lock, but Tracker is per-database and shared and BuildProjectionDaemonAsync is not cached, so two writers can race over the same rows — and the pending dictionary's enumeration order is an implementation detail, not an agreement between them.

Marten's own fix in #5186 does not depend on this bump; the convoy was in Marten's SQL. What this adds is closing the cross-writer deadlock hazard and pinning the contract for the next implementer.

Verification

Restored and built against the published 2.39.2 packages (all five: JasperFx, JasperFx.Events, ComplianceTests, and both source generators).

  • DaemonTests — 300/300 green, net9.0
  • CoreTests jasper_fx_mechanics (the extended-progression configuration tests) — 18/18 green, net9.0

🤖 Generated with Claude Code

https://claude.ai/code/session_017CTtw2kVRSZKp1p5RTxgAy

#630 (marten#5167), the companion to #5186. Two changes:

The IEventDatabase batched extended-progression contract now REQUIRES one row per
transaction rather than asking for "as few round-trips as the store can manage". The old
wording said nothing about transaction scope, which is what made Marten's single
`UPDATE ... FROM unnest(...)` a reasonable reading of it -- and that statement holds a row
lock on every shard in the batch until it commits. Polecat needs the corrected contract
before it implements the batched overload.

ExtendedProgressionWriter now flushes each batch ordered by shard name. With one row per
transaction a single writer never holds more than one row lock, but the tracker is
per-database and shared and BuildProjectionDaemonAsync is not cached, so two writers can
race over the same rows; the pending dictionary's enumeration order is an implementation
detail rather than an agreement between them.

Marten's own fix (#5186) does not depend on this bump -- the convoy was in Marten's SQL.
What this adds is the cross-writer deadlock hazard being closed and the contract being
stated for the next implementer.

DaemonTests 300/300 and CoreTests jasper_fx_mechanics 18/18 green on net9.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017CTtw2kVRSZKp1p5RTxgAy
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