Spun out of GH-4439 as an investigation rather than a bug report, because I have not yet built a case that reproduces user-visible damage.
The observation
MartenPersistenceFrameProvider.DetermineSagaIdType resolves the identity type through the default store:
public Type DetermineSagaIdType(Type sagaType, IServiceContainer container)
{
var store = container.GetInstance<IDocumentStore>();
var documentType = store.Options.FindOrResolveDocumentType(sagaType);
return documentType.IdType;
}
This is the same store-blindness GH-4439 fixed one call later in the same method. WriteModelAttribute.Modify calls DetermineSagaIdType to get the id type it then searches the message for, so for a handler routed to an ancillary store with [MartenStore(typeof(IMyStore))] / [Storage(typeof(IMyStore))], the id type comes from a store that is not the one the handler writes to.
For the common case this is harmless: the aggregate is not registered on the default store, Marten resolves a document mapping for it on the fly, and a plain Guid Id yields Guid either way. The question is what happens when the two stores would not agree, e.g.
- the ancillary store configures the document's identity explicitly (
options.Schema.For<Order>().Identity(x => x.Key)) and the default store does not;
- a strong-typed id, or
StreamIdentity.AsString on one store and not the other;
- a type registered as a document on both stores with different id members.
Scope
Marten only. Polecat and Fisher reflect over the aggregate's Id property and consult no store at all (PolecatPersistenceFrameProvider.cs:33, FisherPersistenceFrameProvider.cs:33), so they have no store to be wrong about — though that is its own asymmetry worth noting.
What would close this
Either a failing test showing a handler on an ancillary store getting the wrong identity type, which turns this into a bug with the GH-4439 fix shape (read chain.AncillaryStoreType, fall back to the default store) — or a demonstration that Marten's per-store document configuration can never diverge in a way that reaches this call, in which case a comment saying so is the right outcome.
Refs GH-4439.
Spun out of GH-4439 as an investigation rather than a bug report, because I have not yet built a case that reproduces user-visible damage.
The observation
MartenPersistenceFrameProvider.DetermineSagaIdTyperesolves the identity type through the default store:This is the same store-blindness GH-4439 fixed one call later in the same method.
WriteModelAttribute.ModifycallsDetermineSagaIdTypeto get the id type it then searches the message for, so for a handler routed to an ancillary store with[MartenStore(typeof(IMyStore))]/[Storage(typeof(IMyStore))], the id type comes from a store that is not the one the handler writes to.For the common case this is harmless: the aggregate is not registered on the default store, Marten resolves a document mapping for it on the fly, and a plain
Guid IdyieldsGuideither way. The question is what happens when the two stores would not agree, e.g.options.Schema.For<Order>().Identity(x => x.Key)) and the default store does not;StreamIdentity.AsStringon one store and not the other;Scope
Marten only. Polecat and Fisher reflect over the aggregate's
Idproperty and consult no store at all (PolecatPersistenceFrameProvider.cs:33,FisherPersistenceFrameProvider.cs:33), so they have no store to be wrong about — though that is its own asymmetry worth noting.What would close this
Either a failing test showing a handler on an ancillary store getting the wrong identity type, which turns this into a bug with the GH-4439 fix shape (read
chain.AncillaryStoreType, fall back to the default store) — or a demonstration that Marten's per-store document configuration can never diverge in a way that reaches this call, in which case a comment saying so is the right outcome.Refs GH-4439.