From 67f1773d4ee47af3efd9169e8d52338d267fdd50 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sat, 28 Mar 2026 00:28:29 -0400 Subject: [PATCH] Add InMemoryStore create_run retry and conflict test Covers the idempotent retry path (same run_id + same created_at) and the conflict rejection path (same run_id + different created_at returns RunAlreadyExists). This was already tested in the SlateStore suite but missing from the InMemoryStore tests. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/crates/fabro-store/src/memory.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/lib/crates/fabro-store/src/memory.rs b/lib/crates/fabro-store/src/memory.rs index 377dc45ce..8962adf38 100644 --- a/lib/crates/fabro-store/src/memory.rs +++ b/lib/crates/fabro-store/src/memory.rs @@ -1049,4 +1049,24 @@ mod tests { store.delete_run("run-1").await.unwrap(); assert!(store.open_run("run-1").await.unwrap().is_none()); } + + #[tokio::test] + async fn create_run_allows_retry_and_rejects_conflict() { + let store = InMemoryStore::default(); + let ts = dt("2026-03-27T12:00:00Z"); + + // First create succeeds. + store.create_run("run-1", ts).await.unwrap(); + + // Retry with exact same created_at succeeds (idempotent). + store.create_run("run-1", ts).await.unwrap(); + + // Different created_at for the same run_id is rejected. + let different_ts = dt("2026-03-27T12:00:01Z"); + match store.create_run("run-1", different_ts).await { + Err(StoreError::RunAlreadyExists(_)) => {} // expected + Err(other) => panic!("expected RunAlreadyExists, got: {other:?}"), + Ok(_) => panic!("expected RunAlreadyExists, but create_run succeeded"), + } + } }