Skip to content

Commit 0d2d71a

Browse files
committed
Cover insert cache behavior on persist failure
Add regression coverage for insert's existing persist-before-cache behavior and update datastore reader comments to match the completed write ordering. This finding was discovered by Project Loupe AI-Assisted-By: OpenAI Codex
1 parent 531d52d commit 0d2d71a

1 file changed

Lines changed: 16 additions & 6 deletions

File tree

src/data_store.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ where
143143
/// Returns the current in-memory object for `id`.
144144
///
145145
/// The async mutation lock serializes writers, but this synchronous reader cannot wait on it.
146-
/// Until store reads are async, callers may temporarily see in-memory state that is either
147-
/// still being persisted or has not yet caught up to a write in progress.
146+
/// Until store reads are async, callers may temporarily see in-memory state that has not yet
147+
/// caught up to a write in progress.
148148
pub(crate) fn get(&self, id: &SO::Id) -> Option<SO> {
149149
self.objects.lock().expect("lock").get(id).cloned()
150150
}
@@ -173,8 +173,8 @@ where
173173
/// Returns in-memory objects matching `f`.
174174
///
175175
/// The async mutation lock serializes writers, but this synchronous reader cannot wait on it.
176-
/// Until store reads are async, callers may temporarily see in-memory state that is either
177-
/// still being persisted or has not yet caught up to a write in progress.
176+
/// Until store reads are async, callers may temporarily see in-memory state that has not yet
177+
/// caught up to a write in progress.
178178
pub(crate) fn list_filter<F: FnMut(&&SO) -> bool>(&self, f: F) -> Vec<SO> {
179179
self.objects.lock().expect("lock").values().filter(f).cloned().collect::<Vec<SO>>()
180180
}
@@ -214,8 +214,8 @@ where
214214
/// Returns whether the in-memory store contains `id`.
215215
///
216216
/// The async mutation lock serializes writers, but this synchronous reader cannot wait on it.
217-
/// Until store reads are async, callers may temporarily see in-memory state that is either
218-
/// still being persisted or has not yet caught up to a write in progress.
217+
/// Until store reads are async, callers may temporarily see in-memory state that has not yet
218+
/// caught up to a write in progress.
219219
pub(crate) fn contains_key(&self, id: &SO::Id) -> bool {
220220
self.objects.lock().expect("lock").contains_key(id)
221221
}
@@ -412,6 +412,16 @@ mod tests {
412412
assert!(data_store.get(&new_id).is_none());
413413
}
414414

415+
#[tokio::test]
416+
async fn insert_does_not_mutate_memory_if_persist_fails() {
417+
let id = TestObjectId { id: [42u8; 4] };
418+
let object = TestObject { id, data: [23u8; 3] };
419+
let data_store = new_failing_data_store(vec![]);
420+
421+
assert_eq!(Err(Error::PersistenceFailed), data_store.insert(object).await);
422+
assert!(data_store.get(&id).is_none());
423+
}
424+
415425
#[tokio::test]
416426
async fn update_does_not_mutate_memory_if_persist_fails() {
417427
let id = TestObjectId { id: [42u8; 4] };

0 commit comments

Comments
 (0)