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>
25 lines
963 B
Plaintext
25 lines
963 B
Plaintext
; persist/concurrency — optimistic concurrency for the log facet. The caller
|
|
; passes the seq it believes is current (the last-seq it last observed). If the
|
|
; stream has advanced since, the append is refused and a conflict VALUE is
|
|
; returned — never a crash, never a silent overwrite. The caller re-reads the
|
|
; tail and retries. This is the substrate-level answer to "two writers, one
|
|
; stream": the loser gets a result it can act on.
|
|
; Requires: lib/persist/log.sx.
|
|
|
|
(define
|
|
persist/append-expect
|
|
(fn
|
|
(b stream expected type at data)
|
|
(let
|
|
((actual (persist/last-seq b stream)))
|
|
(if
|
|
(= actual expected)
|
|
(persist/append b stream type at data)
|
|
{:actual actual :expected expected :conflict true}))))
|
|
|
|
(define
|
|
persist/conflict?
|
|
(fn (r) (if (has-key? r :conflict) (get r :conflict) false)))
|
|
(define persist/conflict-expected (fn (r) (get r :expected)))
|
|
(define persist/conflict-actual (fn (r) (get r :actual)))
|