; Extension — materialized views: stay current on write, read O(1) via peek.

(define vw-count (fn (acc e) (+ acc 1)))
(define vw (persist/view "order-count" "orders" vw-count 0))

(persist-test "view-name" (persist/view-name vw) "order-count")
(persist-test "view-stream" (persist/view-stream vw) "orders")
(persist-test
  "view-value folds the stream"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "orders" "x" 0 {})
      (persist/append b "orders" "x" 0 {})
      (persist/view-value b vw)))
  2)
(persist-test
  "view-refresh persists a snapshot that peek then reads"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "orders" "x" 0 {})
      (persist/view-refresh b vw)
      (persist/view-peek b vw)))
  1)
(persist-test
  "peek lags an un-refreshed tail"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "orders" "x" 0 {})
      (persist/view-refresh b vw)
      (persist/append b "orders" "x" 0 {})
      (persist/view-peek b vw)))
  1)
(persist-test
  "view-value sees the whole stream even after a stale snapshot"
  (let
    ((b (persist/open)))
    (begin
      (persist/append b "orders" "x" 0 {})
      (persist/view-refresh b vw)
      (persist/append b "orders" "x" 0 {})
      (persist/view-value b vw)))
  2)
(persist-test
  "attached view stays current on publish — peek needs no manual refresh"
  (let
    ((b (persist/open)))
    (let
      ((h (persist/view-attach (persist/hub b) vw)))
      (begin
        (persist/publish h "orders" "x" 0 {})
        (persist/publish h "orders" "x" 0 {})
        (persist/publish h "orders" "x" 0 {})
        (persist/view-peek b vw))))
  3)
(persist-test
  "attached view advances the snapshot seq incrementally"
  (let
    ((b (persist/open)))
    (let
      ((h (persist/view-attach (persist/hub b) vw)))
      (begin
        (persist/publish h "orders" "x" 0 {})
        (persist/publish h "orders" "x" 0 {})
        (persist/project-seq
          (persist/snapshot-load b "order-count" 0)))))
  2)
(persist-test
  "attach only reacts to its own stream"
  (let
    ((b (persist/open)))
    (let
      ((h (persist/view-attach (persist/hub b) vw)))
      (begin
        (persist/publish h "other" "x" 0 {})
        (persist/view-peek b vw))))
  0)
(persist-test
  "materialized view works on the durable backend"
  (let
    ((db (persist/mock-durable (persist/mem-backend))))
    (let
      ((h (persist/view-attach (persist/hub db) vw)))
      (begin
        (persist/publish h "orders" "x" 0 {})
        (persist/publish h "orders" "x" 0 {})
        (persist/view-peek db vw))))
  2)
(persist-test
  "view sum over event data"
  (let
    ((b (persist/open))
      (sumv
        (persist/view
          "rev"
          "sales"
          (fn (acc e) (+ acc (get (persist/event-data e) :amt)))
          0)))
    (begin
      (persist/append b "sales" "sale" 0 {:amt 10})
      (persist/append b "sales" "sale" 1 {:amt 25})
      (persist/view-value b sumv)))
  35)
