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>
This commit is contained in:
parent
14d7c64774
commit
a3cc394241
10 changed files with 767 additions and 999 deletions
|
|
@ -248,18 +248,12 @@ namespace GameCult.Networking
|
|||
});
|
||||
}
|
||||
|
||||
private async Task DeleteAsync(CultNetDatabaseChangeRawMessage message)
|
||||
private Task DeleteAsync(CultNetDatabaseChangeRawMessage message)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(message.RecordKey) || string.IsNullOrWhiteSpace(message.SchemaId)) return;
|
||||
var descriptor = _documents.ResolveDescriptorForSchemaId(message.SchemaId!);
|
||||
var handle = Activator.CreateInstance(
|
||||
typeof(CultRecordHandle<>).MakeGenericType(descriptor.DocumentType),
|
||||
new object[] { new CultRecordKey(message.RecordKey!) });
|
||||
var task = (Task)typeof(CultCache)
|
||||
.GetMethod(nameof(CultCache.DeleteAsync), BindingFlags.Public | BindingFlags.Instance)!
|
||||
.MakeGenericMethod(descriptor.DocumentType)
|
||||
.Invoke(_cache, new[] { handle })!;
|
||||
await task.ConfigureAwait(false);
|
||||
if (string.IsNullOrWhiteSpace(message.RecordKey) || string.IsNullOrWhiteSpace(message.SchemaId)) return Task.CompletedTask;
|
||||
_documents.ResolveDescriptorForSchemaId(message.SchemaId!);
|
||||
_cache.Remove(new CultRecordKey(message.RecordKey!));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void Enqueue(Func<Task> operation)
|
||||
|
|
|
|||
Loading…
Reference in a new issue