diff --git a/src/GameCult.Caching.MessagePack/DirectoryMessagePackBackingStore.cs b/src/GameCult.Caching.MessagePack/DirectoryMessagePackBackingStore.cs
index 6af00795..1fdf07c8 100644
--- a/src/GameCult.Caching.MessagePack/DirectoryMessagePackBackingStore.cs
+++ b/src/GameCult.Caching.MessagePack/DirectoryMessagePackBackingStore.cs
@@ -201,10 +201,7 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
}
Entries[pair.Key] = pair.Value;
- if (existing == null)
- EntryAdded.OnNext(pair.Value);
- else
- EntryUpdated.OnNext(pair.Value);
+ Loaded?.Invoke(pair.Value);
}
foreach (var removedKey in _hydratedKeys.Where(key => !loaded.ContainsKey(key)).ToArray())
@@ -213,7 +210,7 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
continue;
if (Entries.TryRemove(removedKey, out var removed))
- EntryDeleted.OnNext(removed);
+ Unloaded?.Invoke(removed);
_hydratedKeys.Remove(removedKey);
}
@@ -307,8 +304,7 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
///
public override void CommitBatch(
IReadOnlyCollection upserts,
- IReadOnlyCollection deletes,
- bool soft)
+ IReadOnlyCollection deletes)
{
lock (_mutationGate)
{
@@ -331,7 +327,7 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
_deletedKeys.TryRemove(entry.Key.Value, out _);
}
IsDirty = true;
- PushAllCore(soft);
+ PushAllCore();
}
catch
{
@@ -351,13 +347,13 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
}
///
- public override void PushAll(bool soft = false)
+ public override void PushAll()
{
lock (_mutationGate)
- PushAllCore(soft);
+ PushAllCore();
}
- private void PushAllCore(bool soft)
+ private void PushAllCore()
{
if (!IsDirty && !_needsIndexUpgrade)
{
@@ -652,10 +648,7 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
continue;
Entries[pair.Key] = pair.Value;
- if (existing == null)
- EntryAdded.OnNext(pair.Value);
- else
- EntryUpdated.OnNext(pair.Value);
+ Loaded?.Invoke(pair.Value);
}
foreach (var missingKey in selectedKeys.Where(key => !loaded.ContainsKey(key)).ToArray())
@@ -663,7 +656,7 @@ public sealed class DirectoryMessagePackBackingStore : CacheBackingStore
if (_dirtyKeys.ContainsKey(missingKey) || _deletedKeys.ContainsKey(missingKey))
continue;
if (Entries.TryRemove(missingKey, out var removed))
- EntryDeleted.OnNext(removed);
+ Unloaded?.Invoke(removed);
_hydratedKeys.Remove(missingKey);
}
diff --git a/src/GameCult.Caching/CultCache.cs b/src/GameCult.Caching/CultCache.cs
index a722d965..7f1af80e 100644
--- a/src/GameCult.Caching/CultCache.cs
+++ b/src/GameCult.Caching/CultCache.cs
@@ -9,7 +9,6 @@ using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using GameCult.Logging;
using R3;
namespace GameCult.Caching
@@ -1281,7 +1280,6 @@ namespace GameCult.Caching
private readonly SemaphoreSlim _transactionGate = new(1, 1);
private readonly AsyncLocal _ambientTransaction = new();
private readonly object _stateGate = new();
- private ILogger _logger = new NullLogger();
private bool _hasUnflushedMutations;
///
@@ -1314,25 +1312,11 @@ namespace GameCult.Caching
InitializeGlobals();
}
- ///
- /// Gets or sets the cache logger.
- ///
- public ILogger Logger
- {
- get => _logger;
- set => _logger = value ?? new NullLogger();
- }
-
///
/// Gets whether the cache currently holds unflushed mutations in any attached backing store or only in memory.
///
public bool IsDirty => _hasUnflushedMutations || _backingStores.Any(store => store.IsDirty);
- ///
- /// Gets the UTC timestamp of the last successful flush across all attached backing stores.
- ///
- public DateTimeOffset? LastSuccessfulFlushAtUtc { get; private set; }
-
///
/// Gets or sets whether disposing the cache should flush attached dirty backing stores first.
///
@@ -1405,10 +1389,8 @@ namespace GameCult.Caching
{
if (store == null) throw new ArgumentNullException(nameof(store));
store.AttachRegistry(_registry);
- store.Logger = Logger;
- store.EntryAdded.Subscribe(entry => AddStoredDocumentInternal(entry, store, raiseUpdate: true).GetAwaiter().GetResult());
- store.EntryUpdated.Subscribe(entry => AddStoredDocumentInternal(entry, store, raiseUpdate: true).GetAwaiter().GetResult());
- store.EntryDeleted.Subscribe(entry => RemoveStoredDocumentInternal(entry, store, raiseUpdate: true));
+ store.Loaded = entry => AddStoredDocumentInternal(entry, store, raiseUpdate: true);
+ store.Unloaded = entry => RemoveStoredDocumentInternal(entry, store, raiseUpdate: true);
foreach (var entry in _entries.Values.OrderBy(entry => entry.Key.Value, StringComparer.Ordinal))
{
@@ -1441,35 +1423,10 @@ namespace GameCult.Caching
}
}
- ///
- /// Pulls persisted records selected by durable metadata from every attached backing store.
- /// Stores without indexed selection support preserve correctness by performing a full pull.
- ///
- public async Task PullBackingStoreRecordsAsync(Func selector)
- {
- if (selector == null) throw new ArgumentNullException(nameof(selector));
- if (_ambientTransaction.Value != null)
- throw new InvalidOperationException(
- "CultCache hydration cannot run inside a mutation transaction; hydrate before opening the commit scope.");
-
- await _transactionGate.WaitAsync().ConfigureAwait(false);
- try
- {
- foreach (var store in _backingStores)
- store.PullSelected(selector);
-
- _hasUnflushedMutations = _backingStores.Any(store => store.IsDirty);
- }
- finally
- {
- _transactionGate.Release();
- }
- }
-
///
/// Flushes all attached backing stores.
///
- public void FlushAllBackingStores(bool soft = false)
+ public void FlushAllBackingStores()
{
if (_ambientTransaction.Value != null)
throw new InvalidOperationException("A CultCache transaction owns durable commit; do not flush inside its stage callback.");
@@ -1478,11 +1435,10 @@ namespace GameCult.Caching
try
{
foreach (var store in _backingStores)
- FlushBackingStoreCore(store, soft);
-
- RecomputeDirtyState();
- if (!IsDirty)
- LastSuccessfulFlushAtUtc = DateTimeOffset.UtcNow;
+ {
+ store.PushAll();
+ RecomputeDirtyState();
+ }
}
finally
{
@@ -1490,64 +1446,10 @@ namespace GameCult.Caching
}
}
- ///
- /// Flushes all attached backing stores.
- ///
+ // soft is dead. CultCacheStudioWindow reflects on FlushAsync(bool) until Cut 6 rewrites it.
public Task FlushAsync(bool soft = false)
{
- FlushAllBackingStores(soft);
- return Task.CompletedTask;
- }
-
- ///
- /// Flushes one attached backing store.
- ///
- public void FlushBackingStore(CacheBackingStore store, bool soft = false)
- {
- if (store == null) throw new ArgumentNullException(nameof(store));
- if (!_backingStores.Contains(store))
- {
- throw new InvalidOperationException("Backing store is not attached to this cache.");
- }
-
- if (_ambientTransaction.Value != null)
- throw new InvalidOperationException("A CultCache transaction owns durable commit; do not flush inside its stage callback.");
-
- _transactionGate.Wait();
- try
- {
- FlushBackingStoreCore(store, soft);
- }
- finally
- {
- _transactionGate.Release();
- }
- }
-
- private void FlushBackingStoreCore(CacheBackingStore store, bool soft)
- {
- store.PushAll(soft);
- RecomputeDirtyState();
- if (!store.IsDirty)
- {
- LastSuccessfulFlushAtUtc = DateTimeOffset.UtcNow;
- }
- }
-
- ///
- /// Flushes attached backing stores at a lifecycle boundary such as shutdown or assembly reload.
- ///
- public void PrepareForReloadOrShutdown(bool soft = false)
- {
- FlushAllBackingStores(soft);
- }
-
- ///
- /// Flushes attached backing stores at a lifecycle boundary such as shutdown or assembly reload.
- ///
- public Task PrepareForReloadOrShutdownAsync(bool soft = false)
- {
- PrepareForReloadOrShutdown(soft);
+ FlushAllBackingStores();
return Task.CompletedTask;
}
@@ -1556,7 +1458,7 @@ namespace GameCult.Caching
/// async flow. The durable backing store is committed before the live cache and its
/// observers advance; an exception discards the entire staged batch.
///
- public async Task ExecuteTransactionAsync(Func stageAsync, bool soft = false)
+ public async Task ExecuteTransactionAsync(Func stageAsync)
{
if (stageAsync == null) throw new ArgumentNullException(nameof(stageAsync));
if (_ambientTransaction.Value != null)
@@ -1573,7 +1475,7 @@ namespace GameCult.Caching
{
await stageAsync().ConfigureAwait(false);
transaction.Seal();
- changes = CommitTransaction(transaction, soft);
+ changes = CommitTransaction(transaction);
}
finally
{
@@ -1587,14 +1489,14 @@ namespace GameCult.Caching
}
/// Runs a value-producing buffered cache mutation.
- public async Task ExecuteTransactionAsync(Func> stageAsync, bool soft = false)
+ public async Task ExecuteTransactionAsync(Func> stageAsync)
{
if (stageAsync == null) throw new ArgumentNullException(nameof(stageAsync));
T result = default!;
await ExecuteTransactionAsync(async () =>
{
result = await stageAsync().ConfigureAwait(false);
- }, soft).ConfigureAwait(false);
+ }).ConfigureAwait(false);
return result;
}
@@ -1614,10 +1516,8 @@ namespace GameCult.Caching
await _transactionGate.WaitAsync().ConfigureAwait(false);
try
{
- var stored = await AddStoredDocumentInternal(
- CreateStoredDocument(typeof(T), document, handle?.Key),
- source: null,
- raiseUpdate: false).ConfigureAwait(false);
+ var stored = CreateStoredDocument(typeof(T), document, handle?.Key);
+ AddStoredDocumentInternal(stored, source: null, raiseUpdate: false);
return new CultRecordHandle(stored.Key);
}
finally
@@ -1658,10 +1558,8 @@ namespace GameCult.Caching
await _transactionGate.WaitAsync().ConfigureAwait(false);
try
{
- var stored = await AddStoredDocumentInternal(
- CreateStoredDocument(documentType, document, key),
- source: null,
- raiseUpdate: false).ConfigureAwait(false);
+ var stored = CreateStoredDocument(documentType, document, key);
+ AddStoredDocumentInternal(stored, source: null, raiseUpdate: false);
return stored.Key;
}
finally
@@ -1705,33 +1603,17 @@ namespace GameCult.Caching
return Get(key) as T;
}
- ///
- /// Tries to get a typed document by record key.
- ///
- public bool TryGet(CultRecordKey key, out T? document) where T : class
- {
- document = Get(key);
- return document != null;
- }
-
///
/// Gets all cached documents assignable to the requested type.
///
public IEnumerable GetAll() where T : class
- {
- return GetStoredDocuments().Select(entry => (T)entry.Document);
- }
-
- ///
- /// Gets typed cached records with their stable CultCache identities without scanning unrelated documents.
- ///
- public IEnumerable GetStoredDocuments() where T : class
{
lock (_stateGate)
{
var type = typeof(T);
return VisibleStoredDocuments()
.Where(entry => type.IsAssignableFrom(entry.Descriptor.DocumentType))
+ .Select(entry => (T)entry.Document)
.ToArray();
}
}
@@ -1761,15 +1643,6 @@ namespace GameCult.Caching
return null;
}
- ///
- /// Tries to get a typed document by its CultName value.
- ///
- public bool TryGetByName(string name, out T? document) where T : class
- {
- document = GetByName(name);
- return document != null;
- }
-
///
/// Gets a typed document by an indexed value.
///
@@ -1784,23 +1657,6 @@ namespace GameCult.Caching
return null;
}
- ///
- /// Tries to get a typed document by an indexed value.
- ///
- public bool TryGetByIndex(string alias, string value, out T? document) where T : class
- {
- document = GetByIndex(alias, value);
- return document != null;
- }
-
- ///
- /// Resolves a typed document reference against this cache.
- ///
- public T? Resolve(CultRecordRef reference) where T : class
- {
- return Get(reference.Key);
- }
-
///
/// Removes a document by typed handle.
///
@@ -1898,8 +1754,7 @@ namespace GameCult.Caching
}
private IReadOnlyList<(CultStoredDocument Stored, object? Previous, bool Removed)> CommitTransaction(
- CultCacheTransaction transaction,
- bool soft)
+ CultCacheTransaction transaction)
{
var mutations = transaction.SnapshotForCommit()
.OrderBy(pair => pair.Key, StringComparer.Ordinal)
@@ -1932,7 +1787,7 @@ namespace GameCult.Caching
.ToArray();
foreach (var store in _backingStores)
- store.CommitBatch(upserts, deleted, soft);
+ store.CommitBatch(upserts, deleted);
var changes = new List<(CultStoredDocument Stored, object? Previous, bool Removed)>();
lock (_stateGate)
@@ -1964,8 +1819,6 @@ namespace GameCult.Caching
changes.Add((stored, existing?.Document, false));
}
_hasUnflushedMutations = _backingStores.Any(store => store.IsDirty);
- if (!IsDirty)
- LastSuccessfulFlushAtUtc = DateTimeOffset.UtcNow;
}
return changes;
@@ -2051,7 +1904,7 @@ namespace GameCult.Caching
document);
}
- private async Task AddStoredDocumentInternal(
+ private void AddStoredDocumentInternal(
CultStoredDocument stored,
CacheBackingStore? source,
bool raiseUpdate)
@@ -2086,9 +1939,6 @@ namespace GameCult.Caching
{
OnUpdate?.Invoke(existing?.Document, stored.Document);
}
-
- await Task.CompletedTask;
- return stored;
}
private void RemoveStoredDocumentInternal(
@@ -2154,7 +2004,7 @@ namespace GameCult.Caching
descriptor,
instance),
source: null,
- raiseUpdate: false).GetAwaiter().GetResult();
+ raiseUpdate: false);
}
}
@@ -2301,7 +2151,6 @@ namespace GameCult.Caching
public abstract class CacheBackingStore : IDisposable
{
private CultDocumentRegistry? _registry;
- private ILogger _logger = new NullLogger();
private bool _isDirty;
private CultSchemaMigrationReport[] _lastSchemaMigrationReports = Array.Empty();
@@ -2317,15 +2166,6 @@ namespace GameCult.Caching
protected ConcurrentDictionary Entries { get; } =
new(StringComparer.Ordinal);
- ///
- /// Gets or sets the backing store logger.
- ///
- public ILogger Logger
- {
- get => _logger;
- set => _logger = value ?? new NullLogger();
- }
-
///
/// Gets whether the backing store holds staged mutations not yet durably flushed.
///
@@ -2335,11 +2175,6 @@ namespace GameCult.Caching
protected set => _isDirty = value;
}
- ///
- /// Gets the UTC timestamp of the last successful durable flush.
- ///
- public DateTimeOffset? LastSuccessfulFlushAtUtc { get; protected set; }
-
///
/// Gets or sets whether disposing the backing store should flush staged mutations first.
///
@@ -2350,18 +2185,9 @@ namespace GameCult.Caching
///
public IReadOnlyList LastSchemaMigrationReports => _lastSchemaMigrationReports;
- ///
- /// Publishes documents added by the backing store.
- ///
- public Subject EntryAdded { get; } = new();
- ///
- /// Publishes documents updated by the backing store.
- ///
- public Subject EntryUpdated { get; } = new();
- ///
- /// Publishes documents deleted by the backing store.
- ///
- public Subject EntryDeleted { get; } = new();
+ // Set by the cache at attach; a store calls them for records it loads or drops.
+ protected internal Action? Loaded;
+ protected internal Action? Unloaded;
internal void AttachRegistry(CultDocumentRegistry registry)
{
@@ -2401,8 +2227,7 @@ namespace GameCult.Caching
///
public virtual void CommitBatch(
IReadOnlyCollection upserts,
- IReadOnlyCollection deletes,
- bool soft)
+ IReadOnlyCollection deletes)
{
var previousEntries = Entries.ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.Ordinal);
var wasDirty = IsDirty;
@@ -2412,7 +2237,7 @@ namespace GameCult.Caching
Delete(entry);
foreach (var entry in upserts)
Push(entry);
- PushAll(soft);
+ PushAll();
}
catch
{
@@ -2426,9 +2251,9 @@ namespace GameCult.Caching
///
/// Persists all current backing store entries.
///
- public abstract void PushAll(bool soft = false);
+ public abstract void PushAll();
///
- /// Releases backing store event subjects.
+ /// Flushes staged mutations first when FlushOnDispose is set.
///
public virtual void Dispose()
{
@@ -2436,10 +2261,6 @@ namespace GameCult.Caching
{
PushAll();
}
-
- EntryAdded.Dispose();
- EntryUpdated.Dispose();
- EntryDeleted.Dispose();
}
///
@@ -2487,7 +2308,6 @@ namespace GameCult.Caching
protected void MarkFlushSucceeded()
{
IsDirty = false;
- LastSuccessfulFlushAtUtc = DateTimeOffset.UtcNow;
}
}
@@ -2571,16 +2391,13 @@ namespace GameCult.Caching
continue;
}
Entries[stored.Key.Value] = stored;
- if (existing == null)
- EntryAdded.OnNext(stored);
- else
- EntryUpdated.OnNext(stored);
+ Loaded?.Invoke(stored);
}
foreach (var removedKey in Entries.Keys.Where(key => !persistedKeys.Contains(key)).ToArray())
{
if (Entries.TryRemove(removedKey, out var removed))
- EntryDeleted.OnNext(removed);
+ Unloaded?.Invoke(removed);
}
SetLastSchemaMigrationReports(reports);
@@ -2608,7 +2425,7 @@ namespace GameCult.Caching
///
/// Writes the staged snapshot to disk.
///
- public override void PushAll(bool soft = false)
+ public override void PushAll()
{
var snapshot = new CultPersistedStoreSnapshot
{
diff --git a/src/GameCult.Mesh/CultMesh.cs b/src/GameCult.Mesh/CultMesh.cs
index 6dd47f8c..08868ade 100644
--- a/src/GameCult.Mesh/CultMesh.cs
+++ b/src/GameCult.Mesh/CultMesh.cs
@@ -432,7 +432,7 @@ namespace GameCult.Mesh
///
public Task FlushAsync(bool soft = false)
{
- return _host.FlushAsync(soft);
+ return _host.FlushAsync();
}
///
diff --git a/src/GameCult.Networking/CultNetLocal.cs b/src/GameCult.Networking/CultNetLocal.cs
index e884cd8d..87942ce8 100644
--- a/src/GameCult.Networking/CultNetLocal.cs
+++ b/src/GameCult.Networking/CultNetLocal.cs
@@ -100,7 +100,7 @@ namespace GameCult.Networking
///
public Task FlushAsync(bool soft = false)
{
- return Cache.FlushAsync(soft);
+ return Cache.FlushAsync();
}
///
diff --git a/tests/GameCult.Caching.Tests/BackingStoreTests.cs b/tests/GameCult.Caching.Tests/BackingStoreTests.cs
index 6624b9f2..483007cb 100644
--- a/tests/GameCult.Caching.Tests/BackingStoreTests.cs
+++ b/tests/GameCult.Caching.Tests/BackingStoreTests.cs
@@ -178,14 +178,11 @@ namespace GameCult.Caching.Tests
Assert.That(cache.IsDirty, Is.True);
Assert.That(store.IsDirty, Is.True);
- Assert.That(cache.LastSuccessfulFlushAtUtc, Is.Null);
cache.FlushAllBackingStores();
Assert.That(cache.IsDirty, Is.False);
Assert.That(store.IsDirty, Is.False);
- Assert.That(cache.LastSuccessfulFlushAtUtc, Is.Not.Null);
- Assert.That(store.LastSuccessfulFlushAtUtc, Is.Not.Null);
}
finally
{
@@ -213,8 +210,7 @@ namespace GameCult.Caching.Tests
cache.Dispose();
var reopened = await CultCacheMessagePack.OpenAsync(filePath);
- Assert.That(reopened.TryGet(handle.Key, out NamedTestEntry? loaded), Is.True);
- Assert.That(loaded!.Value, Is.EqualTo("magic"));
+ Assert.That(reopened.Get(handle.Key)?.Value, Is.EqualTo("magic"));
}
finally
{
@@ -310,21 +306,11 @@ namespace GameCult.Caching.Tests
using var reopened = await CultCacheMessagePack.OpenAsync(
filePath,
- new CultCacheOpenOptions
- {
- Registry = registry,
- UseDirectoryStore = true,
- DirectoryStoreHydrationFilter = _ => false
- });
+ new CultCacheOpenOptions { Registry = registry, UseDirectoryStore = true });
- Assert.That(reopened.GetGlobal(), Is.Null,
- "the hydration filter owns whether the durable global becomes hot");
- Assert.That(reopened.IsDirty, Is.False,
- "a cold durable global must not stage its schema default as a write");
-
- var globalKey = "global:" + registry.GetRequired().SchemaId;
- await reopened.PullBackingStoreRecordsAsync(metadata => metadata.Key == globalKey);
Assert.That(reopened.GetGlobal()?.Value, Is.EqualTo("durable authority"));
+ Assert.That(reopened.IsDirty, Is.False,
+ "a hydrated durable global must not stage its schema default as a write");
}
finally
{
@@ -444,63 +430,6 @@ namespace GameCult.Caching.Tests
}
}
- [Test]
- public async Task DirectoryMessagePackBackingStore_PullSelected_HydratesMatchingColdPagesOnly()
- {
- var filePath = Path.Combine(Path.GetTempPath(), $"cultlib-tests-{Guid.NewGuid():N}.cc");
- var recordsPath = DirectoryMessagePackBackingStore.DefaultRecordDirectoryPath(filePath);
-
- try
- {
- CultRecordHandle hot;
- CultRecordHandle requested;
- CultRecordHandle unrelated;
- using (var seed = await CultCacheMessagePack.OpenAsync(
- filePath,
- new CultCacheOpenOptions { UseDirectoryStore = true }))
- {
- hot = await seed.UpsertAsync(new NamedTestEntry { Name = "hot", Value = "already-loaded" });
- requested = await seed.UpsertAsync(new NamedTestEntry { Name = "requested", Value = "load-later" });
- unrelated = await seed.UpsertAsync(new NamedTestEntry
- {
- Name = "unrelated",
- Value = new string('u', 1024 * 1024)
- });
- await seed.FlushAsync();
- }
-
- string PageFor(CultRecordHandle handle) =>
- Directory.GetFiles(recordsPath, "*.msgpack").Single(path => string.Equals(
- CultDocumentMessagePackSerialization.DeserializePersistedRecord(File.ReadAllBytes(path)).Key,
- handle.Key.Value,
- StringComparison.Ordinal));
-
- using var selected = await CultCacheMessagePack.OpenAsync(
- filePath,
- new CultCacheOpenOptions
- {
- UseDirectoryStore = true,
- DirectoryStoreHydrationFilter = metadata => metadata.Key == hot.Key.Value
- });
- Assert.That(selected.Get(requested.Key), Is.Null);
-
- using (new FileStream(PageFor(unrelated), FileMode.Open, FileAccess.Read, FileShare.None))
- {
- await selected.PullBackingStoreRecordsAsync(metadata => metadata.Key == requested.Key.Value);
- Assert.That(selected.Get(requested.Key)?.Value, Is.EqualTo("load-later"));
- Assert.That(selected.Get(hot.Key)?.Value, Is.EqualTo("already-loaded"));
- Assert.That(selected.Get(unrelated.Key), Is.Null);
- }
- }
- finally
- {
- if (File.Exists(filePath))
- File.Delete(filePath);
- if (Directory.Exists(recordsPath))
- Directory.Delete(recordsPath, recursive: true);
- }
- }
-
[Test]
public async Task DirectoryMessagePackBackingStore_Loads_Record_When_Manifest_Misses_Catalog_Entry()
{
@@ -876,7 +805,7 @@ namespace GameCult.Caching.Tests
var readerCache = new CultCache();
readerCache.AddBackingStore(readerStore);
var observerRan = false;
- using var subscription = readerStore.EntryAdded.Subscribe(_ =>
+ using var subscription = readerCache.Watch().Subscribe(_ =>
{
if (observerRan)
return;
@@ -1059,7 +988,7 @@ namespace GameCult.Caching.Tests
}
[Test]
- public async Task CultCache_TypedStoredDocumentIndex_Tracks_Upsert_Replacement_And_Removal()
+ public async Task CultCache_GetAll_Tracks_Upsert_Replacement_And_Removal()
{
var cache = new CultCache();
var key = new CultRecordKey("typed-index:named");
@@ -1073,20 +1002,20 @@ namespace GameCult.Caching.Tests
Name = "unrelated"
}, new CultRecordKey("typed-index:unrelated"));
- var initial = cache.GetStoredDocuments().Single();
- Assert.That(initial.Key, Is.EqualTo(key));
- Assert.That(((NamedTestEntry)initial.Document).Value, Is.EqualTo("first"));
+ var initial = cache.GetAll().Single();
+ Assert.That(cache.TryGetHandle(initial)?.Key, Is.EqualTo(key));
+ Assert.That(initial.Value, Is.EqualTo("first"));
await cache.UpsertAsync(typeof(NamedTestEntry), new NamedTestEntry
{
Name = "indexed",
Value = "second"
}, key);
- var replaced = cache.GetStoredDocuments().Single();
- Assert.That(((NamedTestEntry)replaced.Document).Value, Is.EqualTo("second"));
+ var replaced = cache.GetAll().Single();
+ Assert.That(replaced.Value, Is.EqualTo("second"));
Assert.That(cache.Remove(key), Is.True);
- Assert.That(cache.GetStoredDocuments(), Is.Empty);
+ Assert.That(cache.GetAll(), Is.Empty);
}
[Test]