execution_event_family.bend
bendvy-ecs-core@0.1.0.3 · 114 lines · 30 definitions
1import Base
2import bendvy-ecs-core@0.1.0.3/owned_event_log.bend as Log
3
4type Family<-S:Data,-P:Type,-key:String> is Type:
5 Family{identity:U32,open:Bool,log:Log.Log<P>,previous:List<&2,Nat>,current:List<&2,Nat>,nextReader:U32,active:List<&2,U32>,droppedThrough:Nat}
6type Reader<-S:Data,-P:Type,-key:String> is Type:
7 Reader{identity:U32,id:U32,cursor:Nat}
8type Creation<-S:Data,-P:Type,-key:String> is Type:
9 Created{family:Family<S,P,key>}
10 CreationRefused{}
11type Start is Data:
12 Retained{}
13 Future{}
14type Refusal is Data:
15 Closed{}
16 ForeignLog{}
17 Inactive{}
18 ReaderLimit{}
19 MissingPayload{}
20type Publication<-P:Type> is Type:
21 Published{id:Nat}
22 PublicationRefused{payload:P}
23type Registration<-S:Data,-P:Type,-key:String> is Type:
24 Registered{reader:Reader<S,P,key>}
25 RegistrationRefused{reason:Refusal}
26type Reading<-S:Data,-P:Type,-key:String,V:Data> is Type:
27 Item{reader:Reader<S,P,key>,id:Nat,value:V,missed:Nat}
28 Empty{reader:Reader<S,P,key>,missed:Nat}
29 ReadRefused{reader:Reader<S,P,key>,reason:Refusal}
30type Removal<-S:Data,-P:Type,-key:String> is Type:
31 Removed{reader:Reader<S,P,key>}
32 RemovalRefused{reader:Reader<S,P,key>,reason:Refusal}
33type Snapshot is Data:
34 Snapshot{identity:U32,open:Bool,next:Nat,previous:List<&2,Nat>,current:List<&2,Nat>,nextReader:U32,active:List<&2,U32>,droppedThrough:Nat}
35
36def created(~S:Data,~P:Type,~key:String,+identity:U32,valid:Bool) -> Creation<S,P,key>:
37 match valid:
38 case False{}:CreationRefused{}
39 case True{}:Created{Family{identity,True{},Log.empty(~P),[],[],1,[],0n}}
40def allocated(~S:Data,~P:Type,~key:String,+identity:U32) -> Creation<S,P,key>:
41 created(~S,~P,~key,identity,Bool.and(U32.is_lt(0,identity),U32.is_lt(identity,4294967295)))
42def has(+ids:List<&2,U32>,+wanted:U32) -> Bool:
43 match ids:
44 case []:False{}
45 case id <> rest:Bool.or(U32.is_eq(id,wanted),has(rest,wanted))
46def without_selected(equal:Bool,id:U32,rest:List<&2,U32>) -> List<&2,U32>:
47 match equal:
48 case True{}:rest
49 case False{}:id <> rest
50def without(ids:List<&2,U32>,+wanted:U32) -> List<&2,U32>:
51 match ids:
52 case []:[]
53 case +id <> rest:without_selected(U32.is_eq(id,wanted),id,without(rest,wanted))
54def published(~S:Data,~P:Type,~key:String,identity:U32,previous:List<&2,Nat>,current:List<&2,Nat>,nextReader:U32,active:List<&2,U32>,dropped:Nat,result:Log.Log<P> & Nat) -> Family<S,P,key> & Publication<P>:
55 match result:
56 case (log,+id):(Family{identity,True{},log,previous,List.append(&2,Nat,current,[id]),nextReader,active,dropped},Published{id})
57
58
59
60def publish(~S:Data,~P:Type,~key:String,family:Family<S,P,key>,payload:P) -> Family<S,P,key> & Publication<P>:
61 match family:
62 case Family{identity,False{},log,previous,current,nextReader,active,dropped}:(Family{identity,False{},log,previous,current,nextReader,active,dropped},PublicationRefused{payload})
63 case Family{identity,True{},log,previous,current,nextReader,active,dropped}:published(~S,~P,~key,identity,previous,current,nextReader,active,dropped,Log.append(~P,log,payload))
64def starting(start:Start,next:Nat) -> Nat:
65 match start:
66 case Retained{}:0n
67 case Future{}:Nat.sub(next,1n)
68def register_checked(~S:Data,~P:Type,~key:String,start:Start,available:Bool,family:Family<S,P,key>) -> Family<S,P,key> & Registration<S,P,key>:
69 match available family:
70 case False{} family:(family,RegistrationRefused{ReaderLimit{}})
71 case True{} Family{+identity,open,Log.Log{+next,rows},previous,current,+nextReader,active,dropped}:(Family{identity,open,Log.Log{next,rows},previous,current,U32.add(nextReader,1),List.append(&2,U32,active,[nextReader]),dropped},Registered{Reader{identity,nextReader,starting(start,next)}})
72def register(~S:Data,~P:Type,~key:String,start:Start,family:Family<S,P,key>) -> Family<S,P,key> & Registration<S,P,key>:
73 match family:
74 case Family{identity,False{},log,previous,current,nextReader,active,dropped}:(Family{identity,False{},log,previous,current,nextReader,active,dropped},RegistrationRefused{Closed{}})
75 case Family{identity,True{},log,previous,current,+nextReader,active,dropped}:register_checked(~S,~P,~key,start,U32.is_lt(nextReader,4294967295),Family{identity,True{},log,previous,current,nextReader,active,dropped})
76def admission_identity(same:Bool,active:Bool) -> Maybe<&2,Refusal>:
77 match same active:
78 case False{} _:Some{ForeignLog{}}
79 case True{} False{}:Some{Inactive{}}
80 case True{} True{}:None{}
81def admission(open:Bool,identity:U32,actual:U32,id:U32,active:List<&2,U32>) -> Maybe<&2,Refusal>:
82 match open:
83 case False{}:Some{Closed{}}
84 case True{}:admission_identity(U32.is_eq(identity,actual),has(active,id))
85def remove_admitted(~S:Data,~P:Type,~key:String,refusal:Maybe<&2,Refusal>,family:Family<S,P,key>,reader:Reader<S,P,key>) -> Family<S,P,key> & Removal<S,P,key>:
86 match refusal family reader:
87 case Some{reason} family reader:(family,RemovalRefused{reader,reason})
88 case None{} Family{identity,open,log,previous,current,nextReader,active,dropped} Reader{actual,+id,cursor}:(Family{identity,open,log,previous,current,nextReader,without(active,id),dropped},Removed{Reader{actual,id,cursor}})
89def remove(~S:Data,~P:Type,~key:String,family:Family<S,P,key>,reader:Reader<S,P,key>) -> Family<S,P,key> & Removal<S,P,key>:
90 match family reader:
91 case Family{+identity,+open,log,previous,current,nextReader,+active,dropped} Reader{+actual,+id,cursor}:remove_admitted(~S,~P,~key,admission(open,identity,actual,id,active),Family{identity,open,log,previous,current,nextReader,active,dropped},Reader{actual,id,cursor})
92def highest(ids:List<&2,Nat>,+initial:Nat) -> Nat:
93 match ids:
94 case []:initial
95 case id <> rest:highest(rest,Nat.max(initial,id))
96def updated(~S:Data,~P:Type,~key:String,identity:U32,current:List<&2,Nat>,nextReader:U32,active:List<&2,U32>,dropped:Nat,result:Log.Log<P> & List<Log.Row<P>>) -> Family<S,P,key> & List<Log.Row<P>>:
97 match result:
98 case (log,retired):(Family{identity,True{},log,current,[],nextReader,active,dropped},retired)
99
100
101
102def update(~S:Data,~P:Type,~key:String,family:Family<S,P,key>) -> Family<S,P,key> & List<Log.Row<P>>:
103 match family:
104 case Family{identity,False{},log,previous,current,nextReader,active,dropped}:(Family{identity,False{},log,previous,current,nextReader,active,dropped},[])
105 case Family{identity,True{},log,previous,+current,nextReader,active,dropped}:updated(~S,~P,~key,identity,current,nextReader,active,highest(previous,dropped),Log.retain(~P,log,current))
106def shutdown_returned(~S:Data,~P:Type,~key:String,identity:U32,nextReader:U32,dropped:Nat,result:Log.Log<P> & List<Log.Row<P>>) -> Family<S,P,key> & List<Log.Row<P>>:
107 match result:
108 case (log,rows):(Family{identity,False{},log,[],[],nextReader,[],dropped},rows)
109def shutdown(~S:Data,~P:Type,~key:String,family:Family<S,P,key>) -> Family<S,P,key> & List<Log.Row<P>>:
110 match family:
111 case Family{identity,_,log,previous,current,nextReader,_,dropped}:shutdown_returned(~S,~P,~key,identity,nextReader,highest(List.append(&2,Nat,previous,current),dropped),Log.drain(~P,log))
112def snapshot(~S:Data,~P:Type,~key:String,family:Family<S,P,key>) -> Family<S,P,key> & Snapshot:
113 match family:
114 case Family{+identity,+open,Log.Log{+next,rows},+previous,+current,+nextReader,+active,+dropped}:(Family{identity,open,Log.Log{next,rows},previous,current,nextReader,active,dropped},Snapshot{identity,open,next,previous,current,nextReader,active,dropped})