Skip to content

Register the event-subscription family aliases from the ancillary Marten path (GH-3438) - #3451

Merged
jeremydmiller merged 1 commit into
mainfrom
fix/3438-ancillary-managed-distribution-family
Jul 17, 2026
Merged

jeremydmiller merged 1 commit into
mainfrom
fix/3438-ancillary-managed-distribution-family

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Fixes #3438.

The gap

The main-store integration aliases EventSubscriptionAgentFamily to both IAgentFamily and IEventSubscriptionAgentFamily. The ancillary integration registered only the concrete type, with a standing // TODO -- watch the service registrations. So a host whose only store wanting managed distribution is ancillary — no main AddMarten that opts in — registered no IEventSubscriptionAgentFamily. Wolverine's managed distribution and external tooling (CritterWatch's projection admin: rebuild/pause/restart) resolve the family through that interface and got an empty result.

What I found beyond the issue

The issue's repro assumes an AncillaryMartenIntegration.UseWolverineManagedEventSubscriptionDistribution flag — which didn't exist. And the per-store IProjectionCoordinator<T> resolver only consulted the main MartenIntegration, which is null/absent for an ancillary-only host. So the fix is three coordinated parts, not a one-line alias add:

  1. New flag UseWolverineManagedEventSubscriptionDistribution on AncillaryMartenIntegration, mirroring the main store's. This is the opt-in an ancillary-only host previously had no way to express.
  2. Gated alias registration. When the flag is set, the ancillary path registers the two interface aliases via TryAddSingleton — Try so a main store that already aliased them wins and one family instance (it already takes IEnumerable<IEventStore>) covers every store. Gated on the flag because NodeAgentController distributes the agents of every registered IAgentFamily; an ancillary host that never opted in must not suddenly start distributing.
  3. Resolver consults the ancillary flag too, so an ancillary-only host gets the managed WolverineProjectionCoordinator<T> instead of silently falling back to the non-managed coordinator.

Test

ancillary_managed_distribution_family_registration: an ancillary store opts in while the main store deliberately does not, so any family resolving through the interface must come from the ancillary path. Asserts the family resolves through IEventSubscriptionAgentFamily, is present as an IAgentFamily for distribution, and that the ancillary store gets the managed coordinator.

Verified red/green: with the flag present but the registration reverted, all three assertions fail; with the fix they pass. The existing with_ancillary_stores tests (main+ancillary) still pass — no regression on that path. Full wolverine.slnx builds clean (0 warnings).

Note: one unrelated multi-node failover test (tenant_partitioned_distribution_multinode.agents_fail_over...) flaked under full-suite load and passes in isolation; it uses a main store, not ancillary, so it's untouched by this change.

🤖 Generated with Claude Code

…ten path (GH-3438)

The main-store integration aliases EventSubscriptionAgentFamily to IAgentFamily
and IEventSubscriptionAgentFamily; the ancillary integration registered only the
concrete type, with a standing "watch the service registrations" TODO. So a host
whose only store wanting managed distribution is ancillary - no main AddMarten
that opts in - registered no IEventSubscriptionAgentFamily at all. Wolverine's
managed distribution and external tooling (CritterWatch's projection admin) that
resolve the family through the interface got nothing.

AncillaryMartenIntegration gains a UseWolverineManagedEventSubscriptionDistribution
flag mirroring the main store's. When set, the ancillary path registers the two
interface aliases via TryAddSingleton - Try so a main store that already aliased
them wins and one family instance (it already takes IEnumerable<IEventStore>)
covers every store. The aliases are gated on the flag because
NodeAgentController distributes the agents of every registered IAgentFamily; an
ancillary host that never opted in must not suddenly start distributing.

The per-store projection coordinator resolver also consults the ancillary flag
now, not just the main MartenIntegration, so an ancillary-only host gets the
managed WolverineProjectionCoordinator<T> rather than silently falling back to
the non-managed coordinator.

Test: an ancillary store opts in while the main store deliberately does not, so
any family resolving through the interface must come from the ancillary path.
Verified the three assertions fail with the flag present but the registration
absent, and the existing with_ancillary_stores tests still pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jeremydmiller
jeremydmiller merged commit 35d01e7 into main Jul 17, 2026
55 of 56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant