1 import Base 2 import ./world.bend as W 3 import ./system.bend as Sys 4 import ./event_runtime.bend as Ev 5 import ./transaction.bend as T 6 import ./capabilities.bend as Cap 7 import ./owned_event_log.bend as Log 8 import ./owned_event_storage.bend as Storage 9 import ./ordinary_owned_event.bend as Ord 10 11 # One declared reader folds its unread payloads through a confined request cap. 12 # Providers are trusted schema provisioning; payload ownership stays in the log. 13 type Failure is Data: 14 BodyFailed{error:Error} 15 MissingPayload{} 16 type Reply is Type: 17 Reply{outcome:T.Outcome>,args:Args,lagged:Bool} 18 def stopped(~S:Data,~C:Type,~R:Type,~P:Type,~Args:Type,~Error:Data,world:W.World,Nat>,args:Args,outcome:T.Outcome>,lagged:Bool) -> W.World,Nat> & Reply: 19 (world,Reply{outcome,args,lagged}) 20 def visited(~S:Data,~C:Type,~R:Type,~P:Type,~Args:Type,~Error:Data,lagged:Bool,next:W.World,Nat> -> Args -> W.World,Nat> & Reply,result:W.World,Nat> & Log.ReadResult & Args>) -> W.World,Nat> & Reply: 21 match result: 22 case (world,Log.Missing{args}):stopped(~S,~C,~R,~P,~Args,~Error,world,args,T.Failure{MissingPayload{}},lagged) 23 case (world,Log.Found{(T.Failure{error},args)}):stopped(~S,~C,~R,~P,~Args,~Error,world,args,T.Failure{BodyFailed{error}},lagged) 24 case (world,Log.Found{(T.Success{},args)}):next(world,args) 25 def fold_rows(~S:Data,~C:Type,~R:Type,~P:Type,~Request:Type,~Projection:Data,~Args:Type,~Error:Data,~identity:Ord.Domain,~at:P -> Request -> P & Projection,~body:@-H:Type -> @-read:Cap.Request -> H -> Args -> H & (T.Outcome & Args),keys:List<&2,Nat>,world:W.World,Nat>,args:Args,+lagged:Bool) -> W.World,Nat> & Reply: 26 match keys: 27 case []:stopped(~S,~C,~R,~P,~Args,~Error,world,args,T.Success{},lagged) 28 case key <> remaining:visited(~S,~C,~R,~P,~Args,~Error,lagged,nextWorld => nextArgs => fold_rows(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body,remaining,nextWorld,nextArgs,lagged),Storage.read(~S,~C,~R,~P,~Request,~Projection,~Args,~(T.Outcome & Args),~at,~body,world,key,args)) 29 def transported(~S:Data,~C:Type,~R:Type,~P:Type,~Args:Type,~Error:Data,result:W.World,Nat> & Reply) -> Sys.Outcome,Nat>,Unit,Reply>: 30 match result: 31 case (world,reply):Sys.Succeeded{world,reply} 32 def runner(~S:Data,~C:Type,~R:Type,~P:Type,~Request:Type,~Projection:Data,~Args:Type,~Error:Data,~identity:Ord.Domain,~at:P -> Request -> P & Projection,~body:@-H:Type -> @-read:Cap.Request -> H -> Args -> H & (T.Outcome & Args),world:W.World,Nat>,input:Ev.Input) -> Sys.Outcome,Nat>,Unit,Reply>: 33 match input: 34 case Ev.Input{keys,lagged,args}:transported(~S,~C,~R,~P,~Args,~Error,fold_rows(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body,keys,world,args,lagged)) 35 def Registry(~S:Data,~C:Type,~R:Type,~P:Type,~Request:Type,~Projection:Data,~Args:Type,~Error:Data,~identity:Ord.Domain,~at:P -> Request -> P & Projection,~body:@-H:Type -> @-read:Cap.Request -> H -> Args -> H & (T.Outcome & Args)) -> Type:Sys.Registry,Nat,Ev.Input,Unit,Reply,runner(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body)> 36 def define(~S:Data,~C:Type,~R:Type,~P:Type,~Request:Type,~Projection:Data,~Args:Type,~Error:Data,~identity:Ord.Domain,~at:P -> Request -> P & Projection,~body:@-H:Type -> @-read:Cap.Request -> H -> Args -> H & (T.Outcome & Args),runtime:Ev.Runtime,Nat>,name:String) -> Ev.Registered,Nat,Args,Unit,Reply,runner(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body)>: 37 Ev.register(~S,~C,~Storage.Resources,~Nat,~Args,~Unit,~Reply,~runner(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body),runtime,name,[Ord.access(~S,~P,identity,":read")]) 38 # Ev.run performs the existing namespace + registration checks and lazy activation. 39 # The closed runner transports semantic failure separately so affine output is 40 # returned. Restore exactly Ev.run_outcome's failed-reader position afterward. 41 def failed_positions(~S:Data,~C:Type,~R:Type,~P:Type,old:List<&2,Ev.Position>,id:U32,runtime:Ev.Runtime,Nat>) -> Ev.Runtime,Nat>: 42 match runtime: 43 case Ev.Runtime{world,namespace,batches,_,nextReader,+tick,frameStart,boundary,capacity,dropped}: 44 Ev.Runtime{world,namespace,batches,Ev.activate(old,id,Nat.sub(tick,1n)),nextReader,tick,frameStart,boundary,capacity,dropped} 45 def reconciled(~S:Data,~C:Type,~R:Type,~P:Type,~Request:Type,~Projection:Data,~Args:Type,~Error:Data,~identity:Ord.Domain,~at:P -> Request -> P & Projection,~body:@-H:Type -> @-read:Cap.Request -> H -> Args -> H & (T.Outcome & Args),old:List<&2,Ev.Position>,id:U32,result:Ev.RunResult,Nat,Args,Unit,Reply,runner(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body)>) -> Ev.RunResult,Nat,Args,Unit,Reply,runner(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body)>: 46 match result: 47 case Ev.Ran{runtime,reader,registry,Ev.Succeeded{Reply{T.Failure{error},args,lagged}}}: 48 Ev.Ran{failed_positions(~S,~C,~R,~P,old,id,runtime),reader,registry,Ev.Succeeded{Reply{T.Failure{error},args,lagged}}} 49 case result:result 50 51 def run(~S:Data,~C:Type,~R:Type,~P:Type,~Request:Type,~Projection:Data,~Args:Type,~Error:Data,~identity:Ord.Domain,~at:P -> Request -> P & Projection,~body:@-H:Type -> @-read:Cap.Request -> H -> Args -> H & (T.Outcome & Args),runtime:Ev.Runtime,Nat>,reader:Ev.Reader,registry:Sys.Registry,Nat,Ev.Input,Unit,Reply,runner(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body)>,args:Args) -> Ev.RunResult,Nat,Args,Unit,Reply,runner(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body)>: 52 match runtime reader: 53 case Ev.Runtime{world,namespace,batches,+positions,nextReader,tick,frameStart,boundary,capacity,dropped} Ev.Reader{readerNamespace,+id,registryId}: 54 reconciled(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body,positions,id,Ev.run(~S,~C,~Storage.Resources,~Nat,~Args,~Unit,~Reply,~runner(~S,~C,~R,~P,~Request,~Projection,~Args,~Error,~identity,~at,~body),Ev.Runtime{world,namespace,batches,positions,nextReader,tick,frameStart,boundary,capacity,dropped},Ev.Reader{readerNamespace,id,registryId},registry,args))