fix: activate tripartite storage routing outside InitializeAsync - #42
Merged
Conversation
Storage routing is driven by StoreOptions.IsProjectionReadModel, whose registry was built only by Freeze(), which in turn was called only by DocumentStore.InitializeAsync. AddAquila never calls InitializeAsync, so in the documented DI setup the registry stayed empty and IsProjectionReadModel answered false for every type. Reads resolved to DocumentStorage while the projection writers targeted ProjectionStorage unconditionally, so read models were written to one store and read from another: LoadAsync returned null indefinitely, and SingleStreamProjection re-derived from an empty aggregate on every batch because its pre-fold load missed. - Freeze at the end of configuration rather than at the start of I/O: in the DocumentStore constructor, in the QuerySessionBase constructor (sessions can be built directly from StoreOptions), and in AddAquila right after configure, so the polyglot guard reports misconfiguration during startup. - Resolve every read and write through one StoreOptions.GetStorageFor(Type), so a read and a write of the same type cannot disagree about which store holds it. - IsProjectionReadModel now throws when queried before Freeze rather than answering false, so a configuration-ordering mistake cannot silently become a data-routing one. Two adjacent defects had to be fixed to ship this, because freezing earlier makes the polyglot guard run in configurations where it previously never did: - The three storage roles defaulted to three distinct InMemoryStorageProvider instances, so a default StoreOptions read as polyglot and rejected the default Inline lifecycle, naming the same provider on both sides of the comparison. One shared instance now backs all three, and ProjectionStorage falls back to DocumentStorage when not explicitly configured -- a store is polyglot because the caller made it so, never by omission. - Polyglot detection compared provider references, so the segregated extensions (UseCosmosDocuments + UseCosmosEvents) produced distinct instances over one Cosmos account and read as polyglot. Detection now compares ProviderName. Tests: two regression tests reproduce the original symptom (verified failing against the previous behaviour, LoadAsync returning null), plus coverage for the default-options case, same-backend distinct instances, unconfigured projection storage falling back to documents, and Freeze running during AddAquila. Core 334 passed, Cosmos 175 non-integration passed, Redis 49 passed. Async_MultiStreamProjection_Processes_Actual_ChangeFeed_Documents_From_CosmosContainer fails in the full integration run and passes in isolation, identically before and after this change -- a pre-existing order-dependent flake, untouched here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Owner
|
Thanks man! This was the last thing I added and had not had a chance to verify yet. |
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.
Storage routing is driven by StoreOptions.IsProjectionReadModel, whose registry was built only by Freeze(), which in turn was called only by DocumentStore.InitializeAsync. AddAquila never calls InitializeAsync, so in the documented DI setup the registry stayed empty and IsProjectionReadModel answered false for every type. Reads resolved to DocumentStorage while the projection writers targeted ProjectionStorage unconditionally, so read models were written to one store and read from another: LoadAsync returned null indefinitely, and SingleStreamProjection re-derived from an empty aggregate on every batch because its pre-fold load missed.
Two adjacent defects had to be fixed to ship this, because freezing earlier makes the polyglot guard run in configurations where it previously never did:
Tests: two regression tests reproduce the original symptom (verified failing against the previous behaviour, LoadAsync returning null), plus coverage for the default-options case, same-backend distinct instances, unconfigured projection storage falling back to documents, and Freeze running during AddAquila.
Core 334 passed, Cosmos 175 non-integration passed, Redis 49 passed. Async_MultiStreamProjection_Processes_Actual_ChangeFeed_Documents_From_CosmosContainer fails in the full integration run and passes in isolation, identically before and after this change -- a pre-existing order-dependent flake, untouched here.