persist: event schema evolution via upcasters + 9 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 37s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 37s
upcast.sx: register a pure (event -> event) upcaster per type in an immutable registry; read-upcast/project-upcast lift legacy events to the current shape on read so projections see one shape (no version branching, no history rewrite). upcast-data helper merges new :data fields. 171/171. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
44
lib/persist/upcast.sx
Normal file
44
lib/persist/upcast.sx
Normal file
@@ -0,0 +1,44 @@
|
||||
; persist/upcast — event schema evolution. An append-only log keeps events
|
||||
; forever, so old events have old shapes. Rather than migrate stored data (you
|
||||
; can't rewrite history) or branch every projection on version, register an
|
||||
; upcaster per event type: a pure (event -> event) that lifts an old event to
|
||||
; the current shape. Reads pass through the registry so projections see ONE
|
||||
; shape. The registry is an immutable dict the consumer threads (no global
|
||||
; mutable state). Requires: lib/persist/event.sx, lib/persist/log.sx.
|
||||
|
||||
(define persist/upcasters (fn () {}))
|
||||
(define persist/register-upcaster (fn (reg type fn) (assoc reg type fn)))
|
||||
|
||||
; apply the registered upcaster for an event's type, or pass it through unchanged
|
||||
(define
|
||||
persist/upcast
|
||||
(fn
|
||||
(reg e)
|
||||
(let ((f (get reg (persist/event-type e)))) (if f (f e) e))))
|
||||
|
||||
; read a stream with every event lifted to current shape
|
||||
(define
|
||||
persist/read-upcast
|
||||
(fn
|
||||
(b stream reg)
|
||||
(map (fn (e) (persist/upcast reg e)) (persist/read b stream))))
|
||||
|
||||
; project over upcasted events — projections never see a legacy shape
|
||||
(define
|
||||
persist/project-upcast
|
||||
(fn
|
||||
(b stream reg step seed)
|
||||
(reduce step seed (persist/read-upcast b stream reg))))
|
||||
|
||||
; helper: upcast an event's :data by merging in/overriding fields, keeping the
|
||||
; record's stream/seq/type/at. Common upcaster body.
|
||||
(define
|
||||
persist/upcast-data
|
||||
(fn
|
||||
(e new-data)
|
||||
(persist/event
|
||||
(persist/event-stream e)
|
||||
(persist/event-seq e)
|
||||
(persist/event-type e)
|
||||
(persist/event-at e)
|
||||
(merge (persist/event-data e) new-data))))
|
||||
Reference in New Issue
Block a user