; persist/global — a global commit ordering across streams. Per-stream seqs only
; order within a stream; a unified timeline (e.g. feed's home feed, a global
; audit trail) needs a single order across streams. `persist/gappend` appends to
; the target stream and then records a pointer in a reserved $global index whose
; own seq IS the global commit position. Reading the index in order and
; resolving each pointer yields every event in commit order. This is opt-in:
; streams that don't need global ordering use plain persist/append and never
; touch $global. Determinism: the order is the $global append order, replayed
; identically. Requires: lib/persist/log.sx, lib/persist/catalog.sx.

(define persist/global-stream "$global")

; append with a global commit position. Returns the stored stream event; the
; event's global position is the seq of its pointer in $global.
(define
  persist/gappend
  (fn
    (b stream type at data)
    (let
      ((ev (persist/append b stream type at data)))
      (begin (persist/append b persist/global-stream "ref" at {:stream stream :seq (persist/event-seq ev)}) ev))))

; the global index: pointer events in commit order (each pointer's seq = gpos)
(define persist/global-log (fn (b) (persist/read b persist/global-stream)))

; the current global commit position (count of globally-ordered appends)
(define
  persist/global-pos
  (fn (b) (persist/last-seq b persist/global-stream)))

; resolve a pointer event to the actual stream event it references
(define
  persist/resolve-ref
  (fn
    (b ptr)
    (let
      ((d (persist/event-data ptr)))
      (first (persist/read-from b (get d :stream) (get d :seq))))))

; every globally-ordered event, in commit order
(define
  persist/read-global
  (fn
    (b)
    (map (fn (ptr) (persist/resolve-ref b ptr)) (persist/global-log b))))

; pointer events at or after a global position (incremental global consumers)
(define
  persist/global-from
  (fn (b gpos) (persist/read-from b persist/global-stream gpos)))

; fold over all events in global commit order
(define
  persist/project-global
  (fn (b step seed) (reduce step seed (persist/read-global b))))
