Skip to content

Commit 3b7e68e

Browse files
authored
chore: Add read/write mode support for persistent store. (#206)
Adds support for controlling the read/write mode of the persistent store. Added an exception for failure to write to the persistent store. Adds a test suite for the WriteThroughStore. Almost the entire PR size is from tests. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adds persistence mode to `WriteThroughStore` with conditional writes/init and improved apply error handling; wires mode in `FDv2DataSystem`; introduces a comprehensive test suite. > > - **Data system**: > - `FDv2DataSystem`: Pass `configuration.DataSystem.PersistentDataStoreMode` to `WriteThroughStore`. > - **Data store**: > - `WriteThroughStore`: > - Add `_persistenceMode` and ctor param to control persistent store behavior. > - Init/Upsert/Apply write to persistent store only in `ReadWrite` mode; `ReadOnly` skips writes. > - Switch active read store to memory on first initializing payload; `Initialized()` uses `_activeReadStore`. > - In legacy persistence path, throw on failed apply (partial upserts) with clear exception message. > - **Tests**: > - New `WriteThroughStoreTest`: covers constructor behavior, init/get/getAll, upsert, apply (transactional vs legacy), store switching, initialized/selector/status monitoring, dispose, and error handling (including switch-to-memory on persistence failures). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 0e23440. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 0d809f0 commit 3b7e68e

File tree

3 files changed

+1030
-17
lines changed

3 files changed

+1030
-17
lines changed

pkgs/sdk/server/src/Internal/DataSystem/FDv2DataSystem.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ public static FDv2DataSystem Create(Logger logger, Configuration configuration,
6060
var persistentStore =
6161
dataSystemConfiguration.PersistentStore?.Build(clientContext.WithDataStoreUpdates(dataStoreUpdates));
6262

63-
var writeThroughStore = new WriteThroughStore(memoryStore, persistentStore);
63+
var writeThroughStore = new WriteThroughStore(memoryStore, persistentStore,
64+
dataSystemConfiguration.PersistentDataStoreMode);
6465

6566
// TODO: When a persistent store is available we monitor it, is this a consistent choice.
6667
// TODO: Update the responses data store monitoring?

pkgs/sdk/server/src/Internal/DataSystem/WriteThroughStore.cs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,18 @@ internal class WriteThroughStore : IDataStore, ITransactionalDataStore
2626
/// </para>
2727
/// </summary>
2828
private readonly AtomicBoolean _hasReceivedAnInitializingPayload = new AtomicBoolean(false);
29+
30+
private readonly DataSystemConfiguration.DataStoreMode _persistenceMode;
2931

30-
public WriteThroughStore(IDataStore memoryStore, IDataStore persistentStore)
32+
public WriteThroughStore(IDataStore memoryStore, IDataStore persistentStore, DataSystemConfiguration.DataStoreMode persistenceMode)
3133
{
3234
_memoryStore = memoryStore;
3335
_txMemoryStore = (ITransactionalDataStore)_memoryStore;
3436
_persistentStore = persistentStore;
3537
_hasPersistence = persistentStore != null;
3638
// During initializations read will happen from the persistent store.
3739
_activeReadStore = _hasPersistence ? _persistentStore : _memoryStore;
40+
_persistenceMode = persistenceMode;
3841
}
3942

4043
public void Dispose()
@@ -56,8 +59,12 @@ private void Dispose(bool disposing)
5659
public void Init(DataStoreTypes.FullDataSet<DataStoreTypes.ItemDescriptor> allData)
5760
{
5861
_memoryStore.Init(allData);
59-
_persistentStore?.Init(allData);
6062
MaybeSwitchStore();
63+
64+
if (_persistenceMode == DataSystemConfiguration.DataStoreMode.ReadWrite)
65+
{
66+
_persistentStore?.Init(allData);
67+
}
6168
}
6269

6370
public DataStoreTypes.ItemDescriptor? Get(DataStoreTypes.DataKind kind, string key)
@@ -73,7 +80,7 @@ public void Init(DataStoreTypes.FullDataSet<DataStoreTypes.ItemDescriptor> allDa
7380
public bool Upsert(DataStoreTypes.DataKind kind, string key, DataStoreTypes.ItemDescriptor item)
7481
{
7582
var result = _memoryStore.Upsert(kind, key, item);
76-
if (_hasPersistence)
83+
if (_hasPersistence && _persistenceMode == DataSystemConfiguration.DataStoreMode.ReadWrite)
7784
{
7885
result &= _persistentStore.Upsert(kind, key, item);
7986
}
@@ -86,29 +93,30 @@ public bool Upsert(DataStoreTypes.DataKind kind, string key, DataStoreTypes.Item
8693

8794
public bool Initialized()
8895
{
89-
return _hasPersistence ? _persistentStore.Initialized() : _memoryStore.Initialized();
96+
return _activeReadStore.Initialized();
9097
}
9198

9299
public void Apply(DataStoreTypes.ChangeSet<DataStoreTypes.ItemDescriptor> changeSet)
93100
{
94101
_txMemoryStore.Apply(changeSet);
102+
MaybeSwitchStore();
95103

96-
if (_hasPersistence)
104+
if (!_hasPersistence || _persistenceMode != DataSystemConfiguration.DataStoreMode.ReadWrite) return;
105+
106+
if (_persistentStore is ITransactionalDataStore txPersistentStore)
97107
{
98-
if (_persistentStore is ITransactionalDataStore txPersistentStore)
99-
{
100-
txPersistentStore.Apply(changeSet);
101-
}
102-
else
108+
txPersistentStore.Apply(changeSet);
109+
}
110+
else
111+
{
112+
// If an apply fails at init, that will throw on its own, but if it fails via an upsert, then
113+
// we need to throw something to work with the current data source updates implementation.
114+
if (!ApplyToLegacyPersistence(changeSet))
103115
{
104-
if (!ApplyToLegacyPersistence(changeSet))
105-
{
106-
// TODO: Probably throw?
107-
}
116+
// The exception type doesn't matter here, as it will be converted to data store status.
117+
throw new Exception("Failure to apply data set to persistent store.");
108118
}
109119
}
110-
111-
MaybeSwitchStore();
112120
}
113121

114122
public Selector Selector => _txMemoryStore.Selector;

0 commit comments

Comments
 (0)