; persist/batch — commit several events to a stream as one contiguous block.
; Each spec is (type at data). Plain append-batch always appends; the -expect
; form is the transactional commit: it checks the stream is still at `expected`
; before writing ANY event, so a batch is all-or-nothing under a concurrent
; writer (conflict is a value, not a partial write). For an order + its line
; items, an audit entry + its reason, etc. Requires: lib/persist/log.sx.

; append a list of (type at data) specs as one block; returns the stored events
; (a real cons-list, in order, with contiguous seqs)
(define
  persist/append-batch
  (fn
    (b stream specs)
    (reverse
      (reduce
        (fn
          (acc spec)
          (cons
            (persist/append
              b
              stream
              (first spec)
              (nth spec 1)
              (nth spec 2))
            acc))
        (list)
        specs))))

; transactional batch: commit all specs only if the stream is still at expected,
; else return a conflict and write nothing
(define
  persist/append-batch-expect
  (fn
    (b stream expected specs)
    (let
      ((actual (persist/last-seq b stream)))
      (if
        (= actual expected)
        (persist/append-batch b stream specs)
        {:actual actual :expected expected :conflict true}))))
