1 import Base 2 import ./world.bend as W 3 4 # Legacy independent affine readers for the append-only event log. 5 # Registered bounded retention/lag/skip/disposal use event-runtime.bend. 6 # Affine payload streams use the separate owned-event APIs. 7 # Legacy independent reader for one World's append-only Data event log. 8 # Owns a namespace and list offset, not a registered retention lease. Use 9 # event-runtime or typed family readers for bounded retention/lag/skip/disposal. 10 type Reader is Type: 11 Reader{namespace: U32,offset: Nat} 12 # Read returns World, advanced reader and detached unread Data events; 13 # ForeignReader returns World and the original reader without reading the log. 14 # Neither result carries affine event payload ownership. 15 type Observed is Type: 16 Read{world: W.World,reader: Reader,events: List<&2,E>} 17 ForeignReader{world: W.World,reader: Reader} 18 19 def create_join(~S: Data,~C: Type,~R: Type,~E: Data,named: W.World & U32) -> W.World & Reader: 20 (world,namespace) = named 21 (world,Reader{namespace,0n}) 22 23 # Create an independent append-only reader at offset zero, returning World. 24 # Existing events are initially unread. This creates no system registration or 25 # bounded-retention lease; raw Reader construction remains trusted setup. 26 def create(~S: Data,~C: Type,~R: Type,~E: Data,world: W.World) -> W.World & Reader: 27 create_join(~S,~C,~R,~E,W.namespace(~S,~C,~R,~E,world)) 28 29 def read_events(~S: Data,~C: Type,~R: Type,~E: Data,+namespace: U32,+offset: Nat,observed: W.World & List<&2,E>) -> Observed: 30 (world,+events) = observed 31 Read{world,Reader{namespace,List.length(&2,E,events)},List.drop(&2,E,events,offset)} 32 33 def read_checked(~S: Data,~C: Type,~R: Type,~E: Data,allowed: Bool,world: W.World,reader: Reader) -> Observed: 34 match allowed reader: 35 case False{} reader: ForeignReader{world,reader} 36 case True{} Reader{+namespace,+offset}: read_events(~S,~C,~R,~E,namespace,offset,W.events_view(~S,~C,~R,~E,world)) 37 38 def read_named(~S: Data,~C: Type,~R: Type,~E: Data,named: W.World & U32,reader: Reader) -> Observed: 39 match named reader: 40 case (world,actual) Reader{+namespace,+offset}: read_checked(~S,~C,~R,~E,U32.is_eq(actual,namespace),world,Reader{namespace,offset}) 41 42 # Read the unread append-only suffix and return the reader at current log 43 # length, preserving event order. Namespace mismatch returns ForeignReader 44 # without accessing events. No registered lifecycle cursor or stream retention 45 # state is advanced. This legacy path has no lag/refusal protocol for log reset. 46 # Example: examples/user-simulation/driver.bend; bounded readers: event-runtime. 47 def read(~S: Data,~C: Type,~R: Type,~E: Data,world: W.World,reader: Reader) -> Observed: 48 read_named(~S,~C,~R,~E,W.namespace(~S,~C,~R,~E,world),reader)