; Phase 4 — durable backend over the IO-suspension boundary, tested with a mock ; transport (the mock-IO harness for the durable protocol). The whole facet ; stack must run unchanged on mock-durable, and a "crash/restart" (drop the ; backend, keep the disk) must recover state by replay. (define dur-count (fn (acc e) (+ acc 1))) ; ---------- request encoders ---------- (persist-test "req-append encodes op + args" (persist/req-append "s" {:k 1}) {:op "persist/append" :args (list "s" {:k 1})}) (persist-test "req-kv-put encodes op + args" (persist/req-kv-put "k" 7) {:op "persist/kv-put" :args (list "k" 7)}) ; ---------- serve round-trips against a disk ---------- (persist-test "serve append then serve read" (let ((disk (persist/mem-backend))) (begin (persist/serve disk (persist/req-append "s" (persist/event "s" 1 "x" 0 {:n 1}))) (get (persist/event-data (first (persist/serve disk (persist/req-read "s")))) :n))) 1) (persist-test "serve kv-put then kv-get" (let ((disk (persist/mem-backend))) (begin (persist/serve disk (persist/req-kv-put "k" 42)) (persist/serve disk (persist/req-kv-get "k")))) 42) (persist-test "serve unknown op is a clear error" (let ((disk (persist/mem-backend))) (guard (e (true "errored")) (persist/serve disk {:op "persist/bogus" :args (list)}))) "errored") ; ---------- full facet stack on mock-durable ---------- (persist-test "log facet works on mock-durable" (let ((db (persist/mock-durable (persist/mem-backend)))) (begin (persist/append db "s" "x" 0 {}) (persist/append db "s" "x" 0 {}) (persist/count db "s"))) 2) (persist-test "seq assignment works on mock-durable" (let ((db (persist/mock-durable (persist/mem-backend)))) (begin (persist/append db "s" "x" 0 {}) (persist/event-seq (persist/append db "s" "x" 0 {})))) 2) (persist-test "kv facet works on mock-durable" (let ((db (persist/mock-durable (persist/mem-backend)))) (begin (persist/kv-put db "k" 5) (persist/kv-get db "k"))) 5) (persist-test "projection works on mock-durable" (let ((db (persist/mock-durable (persist/mem-backend)))) (begin (persist/append db "s" "x" 0 {}) (persist/append db "s" "x" 0 {}) (persist/append db "s" "x" 0 {}) (persist/project-fold db "s" dur-count 0))) 3) (persist-test "snapshot + replay work on mock-durable" (let ((db (persist/mock-durable (persist/mem-backend)))) (begin (persist/append db "s" "x" 0 {}) (persist/append db "s" "x" 0 {}) (persist/checkpoint db "s" "snap" dur-count 0) (persist/append db "s" "x" 0 {}) (persist/project-value (persist/replay db "s" "snap" dur-count 0)))) 3) (persist-test "compaction works on mock-durable" (let ((db (persist/mock-durable (persist/mem-backend)))) (begin (persist/append db "s" "x" 0 {}) (persist/append db "s" "x" 0 {}) (persist/compact db "s" "snap" dur-count 0) (list (persist/count db "s") (persist/last-seq db "s")))) (list 0 2)) ; ---------- crash / restart replay ---------- (persist-test "restart recovers log state from the disk" (let ((disk (persist/mem-backend))) (begin (let ((db (persist/mock-durable disk))) (begin (persist/append db "s" "x" 0 {}) (persist/append db "s" "x" 0 {}))) (let ((db2 (persist/mock-durable disk))) (persist/project-fold db2 "s" dur-count 0)))) 2) (persist-test "restart continues the seq counter" (let ((disk (persist/mem-backend))) (begin (let ((db (persist/mock-durable disk))) (begin (persist/append db "s" "x" 0 {}) (persist/append db "s" "x" 0 {}))) (let ((db2 (persist/mock-durable disk))) (persist/event-seq (persist/append db2 "s" "x" 0 {}))))) 3) (persist-test "restart recovers a kv value" (let ((disk (persist/mem-backend))) (begin (let ((db (persist/mock-durable disk))) (persist/kv-put db "cfg" "on")) (let ((db2 (persist/mock-durable disk))) (persist/kv-get db2 "cfg")))) "on") (persist-test "restart from snapshot equals full replay" (let ((disk (persist/mem-backend))) (begin (let ((db (persist/mock-durable disk))) (begin (persist/append db "s" "x" 0 {}) (persist/append db "s" "x" 0 {}) (persist/checkpoint db "s" "snap" dur-count 0) (persist/append db "s" "x" 0 {}))) (let ((db2 (persist/mock-durable disk))) (equal? (persist/project-value (persist/replay db2 "s" "snap" dur-count 0)) (persist/project-fold db2 "s" dur-count 0))))) true)