@@ -15,6 +15,18 @@ interface WorkerMessage {
1515 processed ?: number
1616}
1717
18+ interface SerializationEvent {
19+ event : "start" | "finish"
20+ messageId : string
21+ at : number
22+ }
23+
24+ interface ExternalEffectEvent {
25+ messageId : string
26+ attempt : number
27+ processId : number
28+ }
29+
1830const directory = await mkdtemp ( join ( tmpdir ( ) , "solid-objects-recovery-" ) )
1931const databasePath = join ( directory , "state.sqlite3" )
2032const runtime = createRuntime ( {
@@ -58,7 +70,10 @@ async function proveSerialization(): Promise<{ finalState: number; overlap: fals
5870 const workers = [ spawnWorker ( ) , spawnWorker ( ) ]
5971 await Promise . all ( workers . map ( ( { finished } ) => finished ) )
6072 await Promise . all ( messages . map ( ( message ) => message . result ( ) ) )
61- const events = await jsonLines ( join ( controlDirectory , "serialization.jsonl" ) )
73+ const events = await readJsonLines (
74+ join ( controlDirectory , "serialization.jsonl" ) ,
75+ parseSerializationEvent ,
76+ )
6277 assert . equal ( events . length , 4 )
6378 const starts = events . filter ( ( event ) => event . event === "start" )
6479 const finishes = events . filter ( ( event ) => event . event === "finish" )
@@ -121,7 +136,10 @@ async function recoveryResult(options: {
121136 const stored = await runtime . repository . findMessage ( options . message . id )
122137 const attempts = Number ( stored ?. attempt_count )
123138 const snapshot = await options . reference . snapshot ( )
124- const effects = await jsonLines ( join ( options . controlDirectory , "external-effects.jsonl" ) )
139+ const effects = await readJsonLines (
140+ join ( options . controlDirectory , "external-effects.jsonl" ) ,
141+ parseExternalEffectEvent ,
142+ )
125143 assert . equal ( attempts , 2 )
126144 assert . equal ( snapshot . count , 1 )
127145 assert . equal ( effects . length , 2 )
@@ -175,12 +193,39 @@ function spawnWorker(): {
175193 }
176194}
177195
178- async function jsonLines ( path : string ) : Promise < Array < Record < string , unknown > > > {
179- return ( await readFile ( path , "utf8" ) )
180- . trim ( )
181- . split ( "\n" )
182- . filter ( Boolean )
183- . map ( ( line ) => JSON . parse ( line ) as Record < string , unknown > )
196+ async function readJsonLines < Value > (
197+ path : string ,
198+ parse : ( line : string ) => Value ,
199+ ) : Promise < Value [ ] > {
200+ return ( await readFile ( path , "utf8" ) ) . trim ( ) . split ( "\n" ) . filter ( Boolean ) . map ( parse )
201+ }
202+
203+ function parseSerializationEvent ( line : string ) : SerializationEvent {
204+ const event = JSON . parse ( line ) as Partial < SerializationEvent >
205+ if (
206+ ( event . event !== "start" && event . event !== "finish" ) ||
207+ typeof event . messageId !== "string" ||
208+ typeof event . at !== "number"
209+ ) {
210+ throw new TypeError ( "invalid serialization event" )
211+ }
212+ return { event : event . event , messageId : event . messageId , at : event . at }
213+ }
214+
215+ function parseExternalEffectEvent ( line : string ) : ExternalEffectEvent {
216+ const event = JSON . parse ( line ) as Partial < ExternalEffectEvent >
217+ if (
218+ typeof event . messageId !== "string" ||
219+ typeof event . attempt !== "number" ||
220+ typeof event . processId !== "number"
221+ ) {
222+ throw new TypeError ( "invalid external effect event" )
223+ }
224+ return {
225+ messageId : event . messageId ,
226+ attempt : event . attempt ,
227+ processId : event . processId ,
228+ }
184229}
185230
186231async function wait ( milliseconds : number ) : Promise < void > {
0 commit comments