Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 58s
Records are name-keyed (defflow registers names); flow-store-export nulls live procs to plain data, flow-store-import! restores, flow-resumable-ids scans for paused flows. Resume re-resolves the proc by name, so a flow survives a wiped store (simulated restart). The whole durable model persists only plain data. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
72 lines
3.8 KiB
Plaintext
72 lines
3.8 KiB
Plaintext
;; lib/flow/tests/recovery.sx — Phase 3: crash recovery (store export/import + restart).
|
|
;;
|
|
;; "restart" is simulated within one program: (set! flow-store (list)) wipes the
|
|
;; in-memory store (process death), while flow-registry persists as it would after
|
|
;; reloading flow definitions. Recovery = import the exported (plain-data) store and
|
|
;; resume; the flow proc is re-resolved by name.
|
|
|
|
(define flow-rec-pass 0)
|
|
(define flow-rec-fail 0)
|
|
(define flow-rec-fails (list))
|
|
|
|
(define
|
|
flow-rec-test
|
|
(fn
|
|
(name actual expected)
|
|
(if
|
|
(= actual expected)
|
|
(set! flow-rec-pass (+ flow-rec-pass 1))
|
|
(begin
|
|
(set! flow-rec-fail (+ flow-rec-fail 1))
|
|
(append! flow-rec-fails {:name name :expected expected :actual actual})))))
|
|
|
|
(define flow-r (fn (src) (flow-run src)))
|
|
|
|
;; ── export / wipe / import ──────────────────────────────────────
|
|
(flow-rec-test
|
|
"export nulls the live procedure"
|
|
(flow-r
|
|
"(defflow w (lambda (x) (suspend (quote await)))) (flow/start w 10) (car (cdr (car (cdr (car (flow-store-export))))))")
|
|
false)
|
|
(flow-rec-test
|
|
"a wiped store loses the flow (process death)"
|
|
(flow-r
|
|
"(defflow w (lambda (x) (suspend (quote await)))) (define id (car (cdr (flow/start w 10)))) (set! flow-store (list)) (flow/resume id 1)")
|
|
(list "flow-error" "no-such-flow"))
|
|
(flow-rec-test
|
|
"import restores a wiped store and resume completes"
|
|
(flow-r
|
|
"(defflow w (sequence (lambda (x) (suspend (quote await))) (lambda (c) (list (quote done) c)))) (define id (car (cdr (flow/start w 10)))) (define saved (flow-store-export)) (set! flow-store (list)) (flow-store-import! saved) (flow/resume id 777)")
|
|
(list "done" 777))
|
|
|
|
;; ── resumable scan ──────────────────────────────────────────────
|
|
(flow-rec-test
|
|
"resumable-ids lists the suspended flow after import"
|
|
(flow-r
|
|
"(defflow w (lambda (x) (suspend (quote await)))) (define id (car (cdr (flow/start w 10)))) (define saved (flow-store-export)) (set! flow-store (list)) (flow-store-import! saved) (flow-resumable-ids)")
|
|
(list 1))
|
|
(flow-rec-test
|
|
"resumable-ids excludes completed flows"
|
|
(flow-r
|
|
"(defflow w (sequence (lambda (x) (suspend (quote await))) (lambda (c) c))) (define id (car (cdr (flow/start w 10)))) (flow/resume id 5) (flow-resumable-ids)")
|
|
(list))
|
|
(flow-rec-test
|
|
"resumable-ids excludes cancelled flows after import"
|
|
(flow-r
|
|
"(defflow w (lambda (x) (suspend (quote await)))) (define id (car (cdr (flow/start w 10)))) (flow/cancel id) (define saved (flow-store-export)) (set! flow-store (list)) (flow-store-import! saved) (flow-resumable-ids)")
|
|
(list))
|
|
|
|
;; ── restart at every step ───────────────────────────────────────
|
|
(flow-rec-test
|
|
"two suspends survive a restart between each step"
|
|
(flow-r
|
|
"(defflow two (sequence (lambda (x) (suspend (quote a))) (lambda (x) (suspend (quote b))) (lambda (x) (list (quote end) x)))) (define id (car (cdr (flow/start two 0)))) (define s1 (flow-store-export)) (set! flow-store (list)) (flow-store-import! s1) (flow/resume id 100) (define s2 (flow-store-export)) (set! flow-store (list)) (flow-store-import! s2) (flow/resume id 200)")
|
|
(list "end" 200))
|
|
(flow-rec-test
|
|
"import preserves the replay log (earlier value survives restart)"
|
|
(flow-r
|
|
"(defflow two (sequence (lambda (x) (suspend (quote a))) (lambda (x) (suspend (quote b))) (lambda (x) (list x)))) (define id (car (cdr (flow/start two 0)))) (flow/resume id 11) (define saved (flow-store-export)) (set! flow-store (list)) (flow-store-import! saved) (flow/resume id 22)")
|
|
(list 22))
|
|
|
|
(define flow-rec-tests-run! (fn () {:total (+ flow-rec-pass flow-rec-fail) :passed flow-rec-pass :failed flow-rec-fail :fails flow-rec-fails}))
|