Summary
In Wolverine 6.23.0, a projection/subscription agent that has been paused and then restarted never comes back. The agent stops correctly on pause, but the restart is accepted and the agent is never re-assigned to any node.
This works in 6.22.0-alpha.3 and fails in 6.23.0 with every other dependency held constant.
Isolation (single variable)
Same test, same clean database, Marten 9.20.0 / JasperFx 2.36.1 / Weasel 9.19.0 / Polecat 5.7.0 held fixed in all runs:
| WolverineFx |
Result |
| 6.22.0-alpha.3 |
✅ 3/3 pass (2 runs) |
| 6.23.0 |
❌ 3/3 fail (2 runs) |
So the regression is in Wolverine itself, not the Marten/JasperFx side of the bump.
Setup
- Marten, database-per-tenant (sharded tenancy, 2 shard databases).
UseWolverineManagedEventSubscriptionDistribution, DurabilityMode.Balanced.
- Each tenant database gets its own projection agent:
event-subscriptions://marten/main/localhost.cw_shardN/trip/all.
- Reproduces at nodeCount: 1 and 3 — it is not multi-node-specific.
Sequence
- Add tenant to shard; wait for that database's Trip agent to be running. ✅
- Pause the agent (a tenant-scoped pause resolving to that database's agent). ✅ agent stops as expected.
- Restart the agent. ❌ the agent never reappears in the running-agent set — 30 s timeout.
At the point of failure, agents for other tenants/shards are running normally, e.g.:
tenant-a Trip agent on cw_shard1 should resume after restart (timed out after 30s; expected present=True).
Cluster: node 1: [event-subscriptions://marten/main/localhost.cw_shard2/trip/all]
and on 3 nodes:
tenant-a Trip agent on cw_shard2 should resume after restart (timed out after 30s; expected present=True).
Cluster: node 1: [] | node 2: [event-subscriptions://marten/main/localhost.cw_shard1/trip/all] | node 3: []
So the grid is alive and distributing other agents — only the previously-paused one is never re-assigned.
Suspected area
The agent changes in 6.23.0, most plausibly one of:
d554b7230 — pending-assignment ledger suppresses duplicate AssignAgent floods (D3/D6)
a9d4a4de1 — scale-safe chunked, bounded-parallel agent batch starts (D3)
f703e1794 — ejection hysteresis + leader protection
38fe0d317 — re-upsert assignment row for already-running agents (D4)
A plausible mechanism, given the symptom: the pause leaves a record that makes the restart's AssignAgent look like a duplicate/in-flight assignment, so the ledger suppresses it and the agent is never actually started. That would explain why the restart is accepted without error yet nothing starts, and why unrelated agents are unaffected.
Impact
Pause/restart of a projection agent is an operator action surfaced in CritterWatch, so on 6.23.0 an operator can pause a tenant's projection and be unable to resume it without a process restart.
Repro
EventStoreCoordinationTests.TenantPartitionedCoordinationTests in JasperFx/CritterWatch:
single_node_per_tenant_pause_then_restart
cluster_per_tenant_pause_then_restart
per_tenant_pause_is_isolated_from_other_tenants
Happy to help narrow it further or test a candidate fix.
Summary
In Wolverine 6.23.0, a projection/subscription agent that has been paused and then restarted never comes back. The agent stops correctly on pause, but the restart is accepted and the agent is never re-assigned to any node.
This works in 6.22.0-alpha.3 and fails in 6.23.0 with every other dependency held constant.
Isolation (single variable)
Same test, same clean database, Marten 9.20.0 / JasperFx 2.36.1 / Weasel 9.19.0 / Polecat 5.7.0 held fixed in all runs:
So the regression is in Wolverine itself, not the Marten/JasperFx side of the bump.
Setup
UseWolverineManagedEventSubscriptionDistribution,DurabilityMode.Balanced.event-subscriptions://marten/main/localhost.cw_shardN/trip/all.Sequence
At the point of failure, agents for other tenants/shards are running normally, e.g.:
and on 3 nodes:
So the grid is alive and distributing other agents — only the previously-paused one is never re-assigned.
Suspected area
The agent changes in 6.23.0, most plausibly one of:
d554b7230— pending-assignment ledger suppresses duplicateAssignAgentfloods (D3/D6)a9d4a4de1— scale-safe chunked, bounded-parallel agent batch starts (D3)f703e1794— ejection hysteresis + leader protection38fe0d317— re-upsert assignment row for already-running agents (D4)A plausible mechanism, given the symptom: the pause leaves a record that makes the restart's
AssignAgentlook like a duplicate/in-flight assignment, so the ledger suppresses it and the agent is never actually started. That would explain why the restart is accepted without error yet nothing starts, and why unrelated agents are unaffected.Impact
Pause/restart of a projection agent is an operator action surfaced in CritterWatch, so on 6.23.0 an operator can pause a tenant's projection and be unable to resume it without a process restart.
Repro
EventStoreCoordinationTests.TenantPartitionedCoordinationTestsin JasperFx/CritterWatch:single_node_per_tenant_pause_then_restartcluster_per_tenant_pause_then_restartper_tenant_pause_is_isolated_from_other_tenantsHappy to help narrow it further or test a candidate fix.