Commit graph CultLib/src/GameCult.Caching.MessagePack/CultCacheMessagePack.cs
Author SHA1 Message Date
Meta Vens
a3cc394241 Route each document type to one home store; attach hydrates; commit explicit batches
Cut 3 of the CultCache migration (Aetheria docs/cultcache-migration-cut.md, 2.1
and 2.2). One commit, because routing, the batch that replaces the ambient
transaction, and conditional commit share one admission path.

Deleted first:
- globals: InitializeGlobals, MaterializeMissingGlobals, the two-argument
  constructor, the initializeGlobals plumbing in CultCacheMessagePack,
  ContainsDurableRecord (cache and directory store)
- replication: the push-to-every-store loops and the attach-time push of
  existing records
- typeof(T) as the schema owner in AddAsync/UpsertAsync and in
  CultNetDatabase.PutAsync/PutPredictedAsync
- the ambient transaction: ExecuteTransactionAsync x2, CultCacheTransaction,
  CommitTransaction, VisibleStoredDocuments, the AsyncLocal, the SemaphoreSlim
  gate, and every ambient check
- CultCacheOpenOptions.PullOnOpen; OpenAsync is Task.FromResult(Create(...))
- DirectoryMessagePackBackingStore.ResolveLegacyUncataloguedRecordCatalog: the
  catalog precommit (fe55bff) is an ancestor of the v4 page format (eea8248),
  so no v4 manifest can reach it
- CultCache.DeleteAsync<T>; its one caller, CultNetDatabaseSubscriptionClient,
  called it by reflection and now calls Remove(key)

Added:
- AddBackingStore(store, params Type[] homes): attach validates (clean, not
  already attached, one untyped store, no claimed home type, no admitted
  record changes home) and then pulls under the gate
- Home(type): most derived routed home, else the untyped store
- Admit: every add and remove, from a write, a batch or a load, validates
  (home, read-only, loaded-from-home, global singleton), lands durably, then
  applies and publishes; a pull hands its whole delta over in one call, so a
  refused record leaves the store and the cache unchanged
- read-only stores (CacheBackingStore(readOnly), both store constructors,
  CultCacheOpenOptions.ReadOnly); flush skips them and writes only dirty stores
- assignable GetGlobal<T>/GetByName<T>/GetByIndex<T>/Watch<T>; more than one
  candidate throws naming them
- Commit(Action<CultCacheBatch>) returning bool, TryCommit returning
  CultCommitOutcome, CultCacheBatch (Upsert, Remove, Expect, ExpectUnchanged,
  sealed after commit), CultCommitRequest; CacheBackingStore.CommitBatch
  evaluates conditions under the store's exclusive lock
- single-file store: <path>.lock sidecar for CommitBatch and PushAll; a clean
  store commits onto the file as it is, so records it never loaded survive
- storedAt minted in one place and bumped a tick when not later than the record
  it replaces

Consumer adjustments in this repo: Mesh streaming tests drop PullOnOpen; the
Studio bridge stops reflecting on it; BackingStoreTests' global test creates
its global explicitly and its transaction tests are rewritten against Commit
(the two that proved ambient hydration rules are deleted); the pre-Cut 2
refusal test expects the attach to throw.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 17:57:58 +02:00
Meta Vens
60cbfdde6d Strip doc comments from the Caching projects
Every /// line in GameCult.Caching and GameCult.Caching.MessagePack goes; they
restated member names. Three blocks that state a rule stay as // comments:
MaterializeMissingGlobals runs after hydration so persisted globals win,
ExecuteTransactionAsync commits durably before the cache and observers
advance, and CommitBatch implementations restore their staged view on
failure. Both projects add NoWarn CS1591, since GenerateDocumentationFile is
on in src/Directory.Build.props.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 16:54:43 +02:00
Meta Vens
59410fc474 Delete unused CultCacheOpenOptions callbacks and directory overrides
ConfigureCache, ConfigureStore, DirectoryStorePath, DirectoryStoreHydrationFilter
and ConfigureDirectoryStore had no consumer outside tests. CreateCore attaches
the directory store at its default record path, or the single-file store,
with no customization hooks. OpenAsync keeps its behavior (pull, then
materialize missing globals); PullOnOpen stays until Cut 3.

The indexed-filter test loses its selective-open half and keeps the v4
manifest assertions: the hot index carries only the SHA-256 page identity and
both records reload.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 16:45:42 +02:00
Meta Vens
d69fa61412 Hydrate durable globals before defaults 2026-07-20 02:23:42 +01:00
Meta Vens
085e177742 Make CultCache hydration subscription-shaped 2026-07-20 01:48:56 +01:00
Meta Vens
086522029c Page CultCache MessagePack records 2026-05-31 17:32:42 +01:00
Meta Vens
80d0485d3c Add ergonomic CultLib happy-path APIs 2026-05-09 13:32:30 +01:00