Make legacy catalog cache read-only

This commit is contained in:
Meta Vens 2026-06-13 06:38:33 +01:00
commit 1872b2ec0b
3 changed files with 33 additions and 4 deletions

View file

@ -18,7 +18,7 @@ public static class LegacyCatalogBoundary
{
if (_catalogCache != null) return _catalogCache;
_catalogCache = new CultCache();
_catalogCache = new CultCache(readOnly: true);
_catalogCache.AddBackingStore(new SingleFileMessagePackBackingStore(GetLegacyCatalogPath(gameDataDirectory)));
_catalogCache.AddBackingStore(new MultiFileMessagePackBackingStore(gameDataDirectory.FullName), typeof(NameFile));
_catalogCache.PullAllBackingStores();

View file

@ -49,9 +49,11 @@ public class CultCache
// private readonly Dictionary<Guid, ExternalEntry> _externalEntries = new Dictionary<Guid, ExternalEntry>();
public IEnumerable<DatabaseEntry> AllEntries => _entries.Values;
public bool ReadOnly { get; }
public CultCache()
public CultCache(bool readOnly = false)
{
ReadOnly = readOnly;
DatabaseLinkBase.Cache = this;
foreach (var type in typeof(DatabaseEntry).GetAllChildClasses())
@ -125,13 +127,19 @@ public class CultCache
{
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;
@ -195,11 +203,21 @@ public class CultCache
_entries.Remove(entry.ID);
var type = entry.GetType();
if(_typeStores.ContainsKey(type))
_typeStores[type].Delete(entry);
{
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())
{
@ -207,6 +225,12 @@ public class CultCache
_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
@ -256,7 +280,7 @@ public abstract class MultiFileBackingStore : CacheBackingStore, RealtimeBacking
DirectoryInfo = new DirectoryInfo(path);
foreach (var type in typeof(DatabaseEntry).GetAllChildClasses())
{
_entryTypeDirectories[type] = DirectoryInfo.CreateSubdirectory(type.Name);
_entryTypeDirectories[type] = new DirectoryInfo(Path.Combine(DirectoryInfo.FullName, type.Name));
}
}
@ -283,6 +307,7 @@ public abstract class MultiFileBackingStore : CacheBackingStore, RealtimeBacking
var type = entry.GetType();
Entries[entry.ID] = entry;
var directory = _entryTypeDirectories[type];
directory.Create();
File.WriteAllBytes(Path.Combine(directory.FullName, GetFileName(entry)), Serialize(entry));
}
@ -308,6 +333,7 @@ public abstract class MultiFileBackingStore : CacheBackingStore, RealtimeBacking
{
foreach (var directory in _entryTypeDirectories.Values)
{
if (!directory.Exists) continue;
var watcher = new FileSystemWatcher(directory.FullName);
watcher.Changed += (sender, args) =>
{

View file

@ -32,6 +32,9 @@ local CultCache, and legacy UI paths should be migration-only or deleted.
`GameData/KeyboardLayouts/*.msgpack` authority paths are disabled or deleted.
The old `SavedGame`/`SavedZone` DTOs and `Galaxy` save-loader constructor are
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.
- `Economy.Server` now starts the modern `Aetheria.State` CultMesh node and no
longer owns RethinkDB/LiteNetLib state.
- `Aetheria.State.Import` writes a typed quarantine manifest and migration