From 8f9852da4d3100b1e9500ae3658d951c0ab77e28 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sat, 13 Jun 2026 07:01:35 +0100 Subject: [PATCH] Collapse legacy backing stores to pull-only --- .../ServerShared/CultCache/CultCache.cs | 153 +----------------- docs/aetheria-perfect-machine-map.md | 7 +- 2 files changed, 5 insertions(+), 155 deletions(-) diff --git a/Assets/Scripts/ServerShared/CultCache/CultCache.cs b/Assets/Scripts/ServerShared/CultCache/CultCache.cs index 43ca95e69..e8b494c62 100644 --- a/Assets/Scripts/ServerShared/CultCache/CultCache.cs +++ b/Assets/Scripts/ServerShared/CultCache/CultCache.cs @@ -3,13 +3,10 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ using System; -using System.Buffers.Text; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using System.Threading.Tasks; using MessagePack; using UniRx; @@ -18,11 +15,6 @@ public class CultCache private readonly object addLock = new object(); - //public Action Logger = Console.WriteLine; - //private string _filePath; - - public event Action OnUpdate; - private List _backingStores = new List(); private readonly Dictionary _typeStores = new Dictionary(); @@ -33,21 +25,6 @@ public class CultCache private readonly Dictionary _globals = new Dictionary(); private readonly Dictionary> _types = new Dictionary>(); - // private readonly Dictionary entries)> _externalTypes = new Dictionary entries)>(); - - // private class ExternalEntry - // { - // public string FilePath; - // public DatabaseEntry Entry; - // - // public ExternalEntry(string filePath, DatabaseEntry entry) - // { - // FilePath = filePath; - // Entry = entry; - // } - // } - // private readonly Dictionary _externalEntries = new Dictionary(); - public IEnumerable AllEntries => _entries.Values; public bool ReadOnly { get; } @@ -75,23 +52,11 @@ public class CultCache } else { - foreach(var existingStore in _backingStores) store.SubscribeTo(existingStore); _backingStores.Add(store); } store.EntryAdded.Subscribe(entry => { Add(entry, store); - OnUpdate?.Invoke(null, entry); - }); - store.EntryUpdated.Subscribe(entry => - { - Add(entry, store); - OnUpdate?.Invoke(entry, entry); - }); - store.EntryDeleted.Subscribe(entry => - { - Remove(entry, store); - OnUpdate?.Invoke(entry, null); }); } @@ -121,25 +86,6 @@ public class CultCache _globals[type] = entry; } - if(_typeStores.ContainsKey(type)) - { - var typeStore = _typeStores[type]; - if(typeStore != source) - { - ThrowIfReadOnlyWrite(); - typeStore.Push(entry); - } - } - else - { - var masterStore = _backingStores.FirstOrDefault(); - if(masterStore != null && masterStore!=source) - { - ThrowIfReadOnlyWrite(); - masterStore.Push(entry); - } - } - _entries[entry.ID] = entry; _types[type].Add(entry); foreach (var parentType in type.GetParentTypes()) @@ -200,40 +146,12 @@ public class CultCache { _entries.Remove(entry.ID); var type = entry.GetType(); - if(_typeStores.ContainsKey(type)) - { - var typeStore = _typeStores[type]; - if(typeStore != source) - { - ThrowIfReadOnlyWrite(); - typeStore.Delete(entry); - } - } - else foreach(var store in _backingStores) - { - if(store != source) - { - ThrowIfReadOnlyWrite(); - store.Delete(entry); - } - } foreach (var parentType in type.GetParentTypes()) { if(_types.ContainsKey(parentType)) _types[parentType].Remove(entry); } } - - private void ThrowIfReadOnlyWrite() - { - if (ReadOnly) - throw new InvalidOperationException("Legacy CultCache is read-only. Durable state belongs to the Verse state spine."); - } -} - -public interface RealtimeBackingStore -{ - public void ObserveChanges(); } public abstract class CacheBackingStore @@ -241,30 +159,16 @@ public abstract class CacheBackingStore protected CacheBackingStore() { EntryAdded = new Subject(); - EntryDeleted = new Subject(); - EntryUpdated = new Subject(); } public abstract void PullAll(); - public abstract void Push(DatabaseEntry entry); - public abstract void Delete(DatabaseEntry entry); - public abstract void PushAll(bool soft = false); public Subject EntryAdded { get; } - public Subject EntryDeleted { get; } - public Subject EntryUpdated { get; } protected Dictionary Entries = new Dictionary(); - - public void SubscribeTo(CacheBackingStore targetStore) - { - targetStore.EntryAdded.Subscribe(Push); - targetStore.EntryDeleted.Subscribe(Delete); - targetStore.EntryUpdated.Subscribe(Push); - } } -public abstract class MultiFileBackingStore : CacheBackingStore, RealtimeBackingStore +public abstract class MultiFileBackingStore : CacheBackingStore { public DirectoryInfo DirectoryInfo { get; } protected Dictionary _entryTypeDirectories = new Dictionary(); @@ -297,47 +201,6 @@ public abstract class MultiFileBackingStore : CacheBackingStore, RealtimeBacking } } - public override void Push(DatabaseEntry entry) - { - throw new NotSupportedException("Legacy multi-file backing stores are read-only migration inputs."); - } - - public override void Delete(DatabaseEntry entry) - { - throw new NotSupportedException("Legacy multi-file backing stores are read-only migration inputs."); - } - - public override void PushAll(bool soft = false) - { - throw new NotSupportedException("Legacy multi-file backing stores are read-only migration inputs."); - } - - public void ObserveChanges() - { - foreach (var directory in _entryTypeDirectories.Values) - { - if (!directory.Exists) continue; - var watcher = new FileSystemWatcher(directory.FullName); - watcher.Changed += (sender, args) => - { - var entry = Deserialize(File.ReadAllBytes(args.FullPath)); - Entries[entry.ID] = entry; - EntryUpdated.OnNext(entry); - }; - watcher.Created += (sender, args) => - { - var entry = Deserialize(File.ReadAllBytes(args.FullPath)); - Entries[entry.ID] = entry; - EntryAdded.OnNext(entry); - }; - watcher.Deleted += (sender, args) => - { - var entry = Deserialize(File.ReadAllBytes(args.FullPath)); - Entries[entry.ID] = entry; - EntryDeleted.OnNext(entry); - }; - } - } } public class MultiFileMessagePackBackingStore : MultiFileBackingStore @@ -383,20 +246,6 @@ public abstract class SingleFileBackingStore : CacheBackingStore } } - public override void Push(DatabaseEntry entry) - { - throw new NotSupportedException("Legacy single-file backing stores are read-only migration inputs."); - } - - public override void Delete(DatabaseEntry entry) - { - throw new NotSupportedException("Legacy single-file backing stores are read-only migration inputs."); - } - - public override void PushAll(bool soft = false) - { - throw new NotSupportedException("Legacy single-file backing stores are read-only migration inputs."); - } } public class SingleFileMessagePackBackingStore : SingleFileBackingStore diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index f7b971663..50f4c1211 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -34,9 +34,9 @@ local CultCache, and legacy UI paths should be migration-only or deleted. deleted. - `LegacyCatalogBoundary` opens the legacy `CultCache` in read-only mode. Old MessagePack backing stores may hydrate in-memory domain objects for the - current Unity runtime, but this path cannot push or delete legacy files. - `SingleFileMessagePackBackingStore` and `MultiFileMessagePackBackingStore` - now throw on `Push`, `Delete`, and `PushAll`. + current Unity runtime, but this path cannot push or delete legacy files. The + legacy backing-store abstraction is pull-only; its write and realtime + watcher APIs have been deleted. - `DatabaseLink.Value` can resolve legacy links only after `LegacyCatalogBoundary` binds the read-only catalog cache. `CultCache` construction no longer grabs global `DatabaseLinkBase` authority. @@ -216,6 +216,7 @@ First Aetheria surfaces to publish: - Done: delete the old `SavedGame`/`SavedZone` runtime save DTO and loader. - Done: stop legacy `CultCache` pull/read paths from writing entries back to their source backing store. + - Done: delete legacy `CultCache` backing-store write/realtime APIs. - Remaining: delete or quarantine old cache abstractions that no longer protect an invariant once catalog migration has a typed reader.