Skip to content

MartenToWolverineOutbox ignores per-store AncillaryMartenIntegration.SchemaName for projection-batch envelope writes #2887

Closed

Description

@erdtsieck

Versions

  • WolverineFx 6.0.0
  • WolverineFx.Marten 6.0.0
  • Marten 9.0.0
  • .NET 10
  • PostgreSQL 18

Setup (modular monolith, ancillary store on a separate physical database)

// Main store on database "main_db", default DatabaseSchemaName "public"
services.AddMarten(opts =>
{
    opts.Connection(mainConn);
}).IntegrateWithWolverine();

// Ancillary store on a different physical database "refs_db"
services.AddMartenStore<IDebtorStore>(opts =>
{
    opts.Connection(refsConn);
    opts.DatabaseSchemaName = "debtors";
}).IntegrateWithWolverine(x => x.SchemaName = "debtors");

An async multi-stream projection registered on IDebtorStore overrides RaiseSideEffects and calls slice.PublishMessage(...).

Reproduction

  1. Drop both databases (fresh state).
  2. Boot the host with AutoCreate.All. pg_tables confirms the expected layout:
    • main_db: public.wolverine_* (12 tables: cluster + envelopes)
    • refs_db: debtors.wolverine_* (7 envelope tables)
  3. Trigger an event that produces a slice for the projection.
  4. Drive ForceAllMartenDaemonActivityToCatchUpAsync<IDebtorStore> (or let the daemon process it).
  5. Projection batch fails:
Npgsql.PostgresException: 42P01: relation "public.wolverine_incoming_envelopes" does not exist
   at Marten.Internal.Sessions.AutoClosingLifetime.ExecuteBatchPagesAsync
   at Marten.Internal.Sessions.DocumentSessionBase.ExecuteBatchAsync
   at Marten.Events.Daemon.Internals.ProjectionBatch.ExecuteAsync
   at JasperFx.Events.Daemon.GroupedProjectionExecution.applyBatchOperationsToDatabaseAsync

Expected

The outbox write for the IDebtorStore projection goes to debtors.wolverine_outgoing_envelopes on refs_db (or whatever the per-store SchemaName is configured to).

Observed

The outbox write targets public.wolverine_incoming_envelopes on refs_db, ignoring the integration's SchemaName. The schema doesn't exist there → 42P01.

Workaround and second symptom

Setting options.Durability.MessageStorageSchemaName = "debtors" globally on WolverineOptions makes the projection-batch outbox write to debtors.wolverine_* correctly for the ancillary store. But at host shutdown, MessageStoreCollection.ReleaseAllOwnershipAsync for the main store now queries debtors.wolverine_incoming_envelopes on main_db, where the debtors schema does not exist (the main Marten store has DatabaseSchemaName = "public"). With AutoCreate.CreateOrUpdate (typical production setting) the debtors schema is not auto-created in main_db and shutdown crashes:

Npgsql.PostgresException: 42P01: relation "debtors.wolverine_incoming_envelopes" does not exist
   at Wolverine.Persistence.MessageStoreCollection.ReleaseAllOwnershipAsync(int nodeNumber)
   at Wolverine.Runtime.WolverineRuntime.StopAsync(CancellationToken cancellationToken)

So we're stuck between two failure modes:

  • Without the global MessageStorageSchemaName → projection-batch outbox writes for the ancillary store ignore the per-store SchemaName and target public.* (wrong location).
  • With the global override → main-store envelope storage targets the override schema in the main DB, which doesn't auto-create with AutoCreate.CreateOrUpdate.

What I verified

  • Envelope tables physically exist in debtors.wolverine_* on refs_db after startup with per-store SchemaName = "debtors" (verified via pg_tables).
  • The failing call comes from MartenToWolverineOutbox inside ProjectionBatch.ExecuteAsync; the SQL it generates uses public.wolverine_*.
  • The full integration test suite (161 tests) on fresh DBs passes with the global override (AutoCreate.All); 14 of them fail without it on the path through slice.PublishMessage in an ancillary-store projection.
  • Reading AncillaryWolverineOptionsMartenExtensions.cs, schema resolution is integration.SchemaName ??= runtime.Options.Durability.MessageStorageSchemaName ?? store.Options.DatabaseSchemaName; — the per-store value should win, but the outbox writer evidently consults a different source.

Ask

Either:

  1. Honour the resolved per-store SchemaName in the projection-batch MartenToWolverineOutbox writer (so the per-store API actually controls envelope writes end-to-end), or
  2. Document a supported configuration for "main + ancillary stores on separate physical databases, each with their own envelope schema".

Happy to put together a minimal repro project if helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions