Skip to content

Upgrade JasperFx to 2.91.0 - #5713

Merged
jeremydmiller merged 2 commits into
masterfrom
claude/jasperfx-2.91.0
Oct 19, 2026
Merged

jeremydmiller merged 2 commits into
masterfrom
claude/jasperfx-2.91.0

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Moves the five JasperFx packages (JasperFx, JasperFx.Events, JasperFx.Events.ComplianceTests, JasperFx.Events.SourceGenerator, JasperFx.SourceGenerator) from 2.90.1 to 2.91.0, released today. The bump spans 2.90.2. The usual note is in Directory.Packages.props.

No Marten code change

  • High-water stall watchdog. In [WIP] npgsql upgrade to 2.0 #1028 the watchdog now calls IHighWaterDetector.FetchCommittedHighWaterCeilingAsync. Marten's HighWaterDetector already implements it.
  • Compliance tests. JasperFx.Events.ComplianceTests is unchanged between 2.90.1 and 2.91.0, so no suite or seam moves.

Picked up through the package

Change Effect on Marten
#1022/#1023 (2.90.2) A drained subscription agent now releases its heartbeat timer. That timer kept the agent, the store and the host alive after the daemon stopped.
#1027/#1028 The HighWaterAgent survives a failed watchdog restart. The watchdog also restarts the agent when the mark stays below the committed ceiling for DaemonSettings.HighWaterProgressStallThreshold (default 2 minutes). A restart re-reads the mark and never advances it, so a gap Marten holds on purpose stays held.
#1025 RewindSubscriptionAsync(name, tenantId, …) now works under UseTenantPartitionedEvents. Behaviour change: under partitioning, the rewind without a tenant now refuses a non-zero sequenceFloor while this daemon runs a tenant agent of that subscription.
#1026 A tenant removed and re-added (RemoveTenantFromShardAsync / AddTenantToShardAsync) is no longer held at its old high-water mark.
#1024 Dynamic LINQ document criteria read date text with no offset as UTC for DateTime members, not only DateTimeOffset ones.
#1021/#1030 The EmittedEvents manifest has one entry per method overload.

One test updated

TenantPartitionedEventsTests.Daemon.rewind_subscription_per_tenant_pin pinned the per-tenant rewind throwing NotSupportedException. Its comment asked for a deliberate flip once per-tenant rewind existed. The fact now runs per_tenant_RewindSubscriptionAsync_replays_only_that_tenant, which checks that:

  1. Rewinding tenant alpha replays alpha's events: its projected document, deleted out of band, comes back with the right state.
  2. Sibling tenant beta's document and progression row are untouched.
  3. Afterwards, the tenant-less rewind refuses sequenceFloor: 1.

The new fact passed 3 of 3 runs.

Local verification (net10.0, PostgreSQL 16)

Suite Result
DaemonTests 377 / 377
TenantPartitionedEventsTests 267 passed, 2 skipped, 0 failed (rerun after the test update; the first run had only the pinned fact failing)
EventSourcingTests 2585 passed, 27 skipped, 0 failed
CoreTests 820 passed, 8 skipped, 0 failed

The net9 jobs are left to CI.


Generated by Claude Code

Moves the five JasperFx packages from 2.90.1 to 2.91.0 (released
2026-10-19), spanning 2.90.2. No Marten code change: Marten's
HighWaterDetector already implements FetchCommittedHighWaterCeilingAsync,
which the new high-water stall watchdog (#1028) calls, and the
compliance suites are unchanged in this range.

Picked up through the package: subscription agents released on stop
(#1022), HighWaterAgent restart fixes (#1027/#1028),
per-tenant subscription rewind (#1025), re-added tenants not held
at their old mark (#1026), UTC date text for DateTime members in
Dynamic LINQ criteria (#1024), and per-overload EmittedEvents
manifest entries (#1021).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017FSnat2TKnusp6MdEZgpHj
rewind_subscription_per_tenant_pin pinned RewindSubscriptionAsync(name,
tenantId, ...) throwing NotSupportedException, so that a per-tenant rewind
landing would flip it deliberately. #1025 implemented it in the
shared daemon. The fact now asserts the behaviour: rewinding one tenant
replays that tenant's events, leaves a sibling tenant's progression row
and documents alone, and the tenant-less rewind then refuses a non-zero
sequence floor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017FSnat2TKnusp6MdEZgpHj
@jeremydmiller
jeremydmiller merged commit 1ad217d into master Oct 19, 2026
32 checks passed
@jeremydmiller
jeremydmiller deleted the claude/jasperfx-2.91.0 branch October 19, 2026 18:59
lahma pushed a commit to lahma/marten that referenced this pull request Oct 20, 2026
Weasel.Postgresql, Weasel.Storage and Weasel.EntityFrameworkCore from
9.45.0 to 9.46.0, spanning 9.45.1. Weasel 9.46.0 needs JasperFx 2.90.2,
which JasperFx#5713 brought in. No Marten code change.

Reaching Marten: weasel#718 finishes a half-built concurrent partitioned
index instead of failing with 42P07 forever, weasel#719 scopes
AdvisoryLock.FindHolderAsync to the current database, and weasel#724
restores a trim annotation on MultiCommandDataReader.GetFieldType.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017FSnat2TKnusp6MdEZgpHj
lahma added a commit to lahma/marten that referenced this pull request Oct 20, 2026
…ojects every event

A tenant removed with RemoveTenantFromShardAsync and re-added with AddTenantToShardAsync
starts fresh: a new per-tenant sequence from 1 and a new agent that catches up from the
tenant's new, empty baseline. The running coordinator can start that agent before the
tenant's first append commits. dynamic_tenant_lifecycle_on_shard_during_daemon leaves that
ordering to a race and failed about one run in ten with "EventCount should be 3 but was 1":
JasperFx's per-tenant high-water bookkeeping still held the mark the removed incarnation
had reached, seeded the new agent with it, and the agent consumed that range as empty
before the new sequence's first events existed.

This test waits for the new agent before appending, so the race goes the same way every
time. It fails on JasperFx 2.90.2 and passes on 2.91.0, which carries the fix
(JasperFx/jasperfx#1026) and which master already consumes through JasperFx#5713.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jeremydmiller pushed a commit that referenced this pull request Oct 23, 2026
JasperFx 2.91.0 (#1025) rewinds a subscription per tenant under
UseTenantPartitionedEvents, through RewindSubscriptionProgressAsync with each tenant
shard's own identity, which Marten accepts since #5700. The daemon logic is pinned in
JasperFx against a substituted store, and rewind_subscription_per_tenant_pin (#5713)
pins a per-tenant rewind of a projection to the beginning. Nothing in Marten pinned the
rest against a live store.

Three facts, with a raw ISubscription and two tenants at heights 5 and 3:

- Rewinding every tenant to the beginning restarts each tenant's own agent, never a
  store-global one, and each replays only its own tenant's events.
- Rewinding one tenant to sequence floor 2 replays only that tenant's events above it,
  deletes only that tenant's dead letters at or above it, and leaves the other tenant's
  agent instance running with its progression and dead letters untouched.
- Rewinding every tenant to a sequence number is refused, and changes no agent, no
  progression row and no dead letter.

All three fail on 8065f44, the master commit before #5700 merged (JasperFx 2.90.1),
and pass on master.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants