persist: optimistic concurrency — conflict as a real result + 8 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
concurrency.sx: persist/append-expect refuses an append when the stream
advanced past the caller's expected seq, returning {:conflict :expected
:actual} instead of crashing or overwriting. persist/conflict? + accessors.
Phase 2 complete, 54/54.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
96
lib/persist/tests/concurrency.sx
Normal file
96
lib/persist/tests/concurrency.sx
Normal file
@@ -0,0 +1,96 @@
|
||||
; Phase 2 — optimistic concurrency: conflict is a real result, not a crash.
|
||||
|
||||
(persist-test
|
||||
"append-expect 0 on empty stream succeeds"
|
||||
(persist/event-seq
|
||||
(persist/append-expect
|
||||
(persist/open)
|
||||
"s"
|
||||
0
|
||||
"x"
|
||||
0
|
||||
{}))
|
||||
1)
|
||||
(persist-test
|
||||
"append-expect with correct seq succeeds"
|
||||
(let
|
||||
((b (persist/open)))
|
||||
(begin
|
||||
(persist/append b "s" "x" 0 {})
|
||||
(persist/event-seq
|
||||
(persist/append-expect b "s" 1 "x" 0 {}))))
|
||||
2)
|
||||
(persist-test
|
||||
"append-expect with stale seq returns a conflict"
|
||||
(let
|
||||
((b (persist/open)))
|
||||
(begin
|
||||
(persist/append b "s" "x" 0 {})
|
||||
(persist/append b "s" "x" 0 {})
|
||||
(persist/conflict?
|
||||
(persist/append-expect b "s" 1 "x" 0 {}))))
|
||||
true)
|
||||
(persist-test
|
||||
"a successful append is not a conflict"
|
||||
(persist/conflict?
|
||||
(persist/append-expect
|
||||
(persist/open)
|
||||
"s"
|
||||
0
|
||||
"x"
|
||||
0
|
||||
{}))
|
||||
false)
|
||||
(persist-test
|
||||
"conflict carries expected and actual"
|
||||
(let
|
||||
((b (persist/open)))
|
||||
(begin
|
||||
(persist/append b "s" "x" 0 {})
|
||||
(persist/append b "s" "x" 0 {})
|
||||
(let
|
||||
((r (persist/append-expect b "s" 0 "x" 0 {})))
|
||||
(list (persist/conflict-expected r) (persist/conflict-actual r)))))
|
||||
(list 0 2))
|
||||
(persist-test
|
||||
"a conflicting append does not write"
|
||||
(let
|
||||
((b (persist/open)))
|
||||
(begin
|
||||
(persist/append b "s" "x" 0 {})
|
||||
(persist/append-expect b "s" 0 "x" 0 {})
|
||||
(persist/count b "s")))
|
||||
1)
|
||||
(persist-test
|
||||
"two writers: first wins, second conflicts"
|
||||
(let
|
||||
((b (persist/open)))
|
||||
(let
|
||||
((seen (persist/last-seq b "s")))
|
||||
(begin
|
||||
(persist/append-expect b "s" seen "x" 0 {:who "A"})
|
||||
(persist/conflict?
|
||||
(persist/append-expect b "s" seen "x" 0 {:who "B"})))))
|
||||
true)
|
||||
(persist-test
|
||||
"retry after conflict succeeds"
|
||||
(let
|
||||
((b (persist/open)))
|
||||
(let
|
||||
((seen (persist/last-seq b "s")))
|
||||
(begin
|
||||
(persist/append-expect b "s" seen "x" 0 {:who "A"})
|
||||
(let
|
||||
((r (persist/append-expect b "s" seen "x" 0 {:who "B"})))
|
||||
(if
|
||||
(persist/conflict? r)
|
||||
(persist/event-seq
|
||||
(persist/append-expect
|
||||
b
|
||||
"s"
|
||||
(persist/conflict-actual r)
|
||||
"x"
|
||||
0
|
||||
{:who "B"}))
|
||||
(persist/event-seq r))))))
|
||||
2)
|
||||
Reference in New Issue
Block a user