GH-4507: declare a module's ancillary store once per namespace - #4508
Merged
jeremydmiller merged 1 commit intoSep 22, 2026
Merged
Conversation
UseAncillaryStorageFromAssembly (JasperFx#4477) assumes one module per assembly. Modular monoliths that start as one project, with a namespace per module so the modules can be split into assemblies later, can't use it: every module in the assembly would get the same store. opts.Policies.UseAncillaryStorageFromNamespaceContaining<OrdersModule>(typeof(IOrdersStore)); Purely additive. AncillaryStorageByNamespacePolicy is a sibling of AncillaryStorageByAssemblyPolicy with the same precedence (an explicit [Storage] or an earlier policy wins) and the same reach (handlers, HTTP endpoints, and gRPC via IChainSourceType). Only the match differs: the handler or endpoint type's namespace, including child namespaces, with a dot boundary so "Orders" does not match "OrdersArchive". Named to match MessagesFromNamespace / MessagesFromNamespaceContaining<T>. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
No unresolved review issues were identified.
Review effort: Lite
Findings: None
What changed in this PR
Adds namespace-scoped ancillary storage policies for modular monoliths sharing an assembly.
Changes:
- Adds namespace-based policy APIs and implementation.
- Adds Core, Marten, and gRPC test coverage.
- Updates ancillary storage documentation.
| File | Description |
|---|---|
src/Wolverine/WolverineOptions.Policies.cs |
Registers namespace policies. |
src/Wolverine/Persistence/AncillaryStorageByNamespacePolicy.cs |
Implements namespace matching. |
src/Wolverine/IPolicies.cs |
Defines public policy APIs. |
src/Wolverine.Grpc.Tests/ancillary_storage_by_namespace_reaches_grpc.cs |
Tests gRPC routing. |
src/Testing/CoreTests/Persistence/ancillary_storage_by_namespace_policy.cs |
Tests routing behavior and boundaries. |
src/Persistence/MartenTests/AncillaryStores/ancillary_storage_by_namespace.cs |
Adds Marten coverage. |
docs/tutorials/modular-monolith.md |
Documents namespace-scoped usage. |
docs/guide/durability/polecat/ancillary-stores.md |
Documents Polecat support. |
docs/guide/durability/marten/ancillary-stores.md |
Documents Marten support. |
docs/guide/durability/fisher/index.md |
Documents Fisher support. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This was referenced Sep 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4507
TL;DR
Adds a namespace-scoped sibling of #4477's assembly policy, for modular monoliths that keep several modules in one assembly. Additive only: no existing code changes.
What changed
Persistence/AncillaryStorageByNamespacePolicy.csAncillaryStorageByAssemblyPolicy: same skip rule, sameUseAncillaryStoragecall, same gRPC reach. Only the match differs.IPolicies.cs,WolverineOptions.Policies.csMessagesFromNamespace/MessagesFromNamespaceContaining<T>.Behaviour
OrdersOrders.Slices(child)OrdersArchive(shares a prefix)Shipping(sibling)[Storage]on the handlerMatching uses the namespace of the handler / endpoint / gRPC service type, not the message.
Review guide (about 5 min)
AncillaryStorageByNamespacePolicy.cs: diff it mentally against the assembly policy.isInNamespaceis the only new logic.IPolicies.cs: the public API and XML docs.ancillary_storage_by_namespace_policy.cs: the table above, as tests.Worth a look
IPoliciesgains two members.WolverineOptionsis its only implementer in the repo, and GH-4477: declare a module's ancillary store once per assembly #4477 extended it the same way.6.39badge headings. Adjust if you want a badge for the release this ships in.Test runs
~ancillary_storage~ancillary_storage_by~ancillary_storageThe Marten docs snippet block is written in mdsnippets' output format (region L57–L64), so a regeneration should produce no diff.
🤖 Generated with Claude Code