; Phase 4 — crash/restart integration. A whole subsystem (an order ledger:
; event log + a kv read model kept by a subscription + a periodic snapshot + an
; invoice blob ref) on the durable backend must survive a restart. "Crash" =
; drop every in-process object (backend, hub, projections); "restart" = rebuild
; them over the SAME disk + blob store. Nothing but the disk and content store
; carries across, exactly as a real process restart.

(define rec-count (fn (acc e) (+ acc 1)))

(persist-test
  "log survives restart and seq continues"
  (let
    ((disk (persist/mem-backend)))
    (begin
      (let
        ((db (persist/mock-durable disk)))
        (begin
          (persist/append db "orders" "placed" 0 {:id "a"})
          (persist/append db "orders" "placed" 1 {:id "b"})))
      (let
        ((db2 (persist/mock-durable disk)))
        (list
          (persist/project-fold db2 "orders" rec-count 0)
          (persist/event-seq
            (persist/append db2 "orders" "placed" 2 {:id "c"}))))))
  (list 2 3))
(persist-test
  "subscription-driven kv read model survives restart"
  (let
    ((disk (persist/mem-backend)))
    (begin
      (let
        ((h (persist/hub (persist/mock-durable disk))))
        (begin
          (persist/subscribe
            h
            "orders"
            (fn
              (bk s e)
              (persist/kv-update
                bk
                "order-count"
                0
                (fn (n) (+ n 1)))))
          (persist/publish h "orders" "placed" 0 {})
          (persist/publish h "orders" "placed" 1 {})))
      (let
        ((db2 (persist/mock-durable disk)))
        (persist/kv-get db2 "order-count"))))
  2)
(persist-test
  "snapshot taken before crash drives replay after restart"
  (let
    ((disk (persist/mem-backend)))
    (begin
      (let
        ((db (persist/mock-durable disk)))
        (begin
          (persist/append db "orders" "placed" 0 {})
          (persist/append db "orders" "placed" 1 {})
          (persist/checkpoint db "orders" "count" rec-count 0)
          (persist/append db "orders" "placed" 2 {})))
      (let
        ((db2 (persist/mock-durable disk)))
        (equal?
          (persist/project-value
            (persist/replay db2 "orders" "count" rec-count 0))
          (persist/project-fold db2 "orders" rec-count 0)))))
  true)
(persist-test
  "compacted log still replays correctly after restart"
  (let
    ((disk (persist/mem-backend)))
    (begin
      (let
        ((db (persist/mock-durable disk)))
        (begin
          (persist/append db "orders" "placed" 0 {})
          (persist/append db "orders" "placed" 1 {})
          (persist/append db "orders" "placed" 2 {})
          (persist/compact db "orders" "count" rec-count 0)
          (persist/append db "orders" "placed" 3 {})))
      (let
        ((db2 (persist/mock-durable disk)))
        (persist/project-value
          (persist/replay db2 "orders" "count" rec-count 0)))))
  4)
(persist-test
  "invoice blob ref survives restart, bytes fetched from content store"
  (let
    ((disk (persist/mem-backend)) (store (persist/mem-backend)))
    (begin
      (let
        ((db (persist/mock-durable disk)) (blob (persist/mock-blob store)))
        (persist/kv-put
          db
          "invoice"
          (persist/blob-store blob "INVOICEPDF" "application/pdf")))
      (let
        ((db2 (persist/mock-durable disk))
          (blob2 (persist/mock-blob store)))
        (persist/blob-fetch blob2 (persist/kv-get db2 "invoice")))))
  "INVOICEPDF")
(persist-test
  "two independent restarts converge to the same state (determinism)"
  (let
    ((disk (persist/mem-backend)))
    (begin
      (let
        ((db (persist/mock-durable disk)))
        (begin
          (persist/append db "orders" "placed" 0 {})
          (persist/append db "orders" "placed" 1 {})
          (persist/append db "orders" "placed" 2 {})))
      (equal?
        (persist/project-fold
          (persist/mock-durable disk)
          "orders"
          rec-count
          0)
        (persist/project-fold
          (persist/mock-durable disk)
          "orders"
          rec-count
          0))))
  true)
