@@ -128,72 +128,80 @@ export class Store<TSchema extends LiveStoreSchema = LiveStoreSchema.Any, TConte
128
128
schema,
129
129
clientSession,
130
130
runtime : effectContext . runtime ,
131
- materializeEvent : ( eventDecoded , { otelContext, withChangeset, materializerHashLeader } ) => {
132
- const { eventDef, materializer } = getEventDef ( schema , eventDecoded . name )
133
-
134
- const execArgsArr = getExecStatementsFromMaterializer ( {
135
- eventDef,
136
- materializer,
137
- dbState : this . sqliteDbWrapper ,
138
- event : { decoded : eventDecoded , encoded : undefined } ,
139
- } )
140
-
141
- const materializerHash = isDevEnv ( ) ? Option . some ( hashMaterializerResults ( execArgsArr ) ) : Option . none ( )
142
-
143
- if (
144
- materializerHashLeader . _tag === 'Some' &&
145
- materializerHash . _tag === 'Some' &&
146
- materializerHashLeader . value !== materializerHash . value
147
- ) {
148
- void this . shutdown (
149
- Cause . fail (
150
- UnexpectedError . make ( {
151
- cause : `Materializer hash mismatch detected for event "${ eventDecoded . name } ".` ,
152
- note : `Please make sure your event materializer is a pure function without side effects.` ,
153
- } ) ,
154
- ) ,
155
- )
156
- }
157
-
158
- const writeTablesForEvent = new Set < string > ( )
159
-
160
- const exec = ( ) => {
161
- for ( const {
162
- statementSql,
163
- bindValues,
164
- writeTables = this . sqliteDbWrapper . getTablesUsed ( statementSql ) ,
165
- } of execArgsArr ) {
166
- try {
167
- this . sqliteDbWrapper . cachedExecute ( statementSql , bindValues , { otelContext, writeTables } )
168
- } catch ( cause ) {
169
- throw UnexpectedError . make ( {
170
- cause,
171
- note : `Error executing materializer for event "${ eventDecoded . name } ".\nStatement: ${ statementSql } \nBind values: ${ JSON . stringify ( bindValues ) } ` ,
172
- } )
173
- }
174
-
175
- // durationMsTotal += durationMs
176
- for ( const table of writeTables ) {
177
- writeTablesForEvent . add ( table )
131
+ materializeEvent : Effect . fn ( 'client-session-sync-processor:materialize-event' ) (
132
+ ( eventDecoded , { otelContext, withChangeset, materializerHashLeader } ) =>
133
+ Effect . gen ( this , function * ( ) {
134
+ const { eventDef, materializer } = getEventDef ( schema , eventDecoded . name )
135
+
136
+ const execArgsArr = getExecStatementsFromMaterializer ( {
137
+ eventDef,
138
+ materializer,
139
+ dbState : this . sqliteDbWrapper ,
140
+ event : { decoded : eventDecoded , encoded : undefined } ,
141
+ } )
142
+
143
+ const materializerHash = isDevEnv ( ) ? Option . some ( hashMaterializerResults ( execArgsArr ) ) : Option . none ( )
144
+
145
+ if (
146
+ materializerHashLeader . _tag === 'Some' &&
147
+ materializerHash . _tag === 'Some' &&
148
+ materializerHashLeader . value !== materializerHash . value
149
+ ) {
150
+ // Fork the shutdown effect to run in the background as a daemon, ensuring it's not interrupted.
151
+ // TODO: we should probably handle this more gracefully using Effect’s error channel
152
+ yield * Effect . forkDaemon (
153
+ this . shutdown (
154
+ Cause . fail (
155
+ UnexpectedError . make ( {
156
+ cause : `Materializer hash mismatch detected for event "${ eventDecoded . name } ".` ,
157
+ note : `Please make sure your event materializer is a pure function without side effects.` ,
158
+ } ) ,
159
+ ) ,
160
+ ) ,
161
+ )
178
162
}
179
163
180
- this . sqliteDbWrapper . debug . head = eventDecoded . seqNum
181
- }
182
- }
183
-
184
- let sessionChangeset :
185
- | { _tag : 'sessionChangeset' ; data : Uint8Array ; debug : any }
186
- | { _tag : 'no-op' }
187
- | { _tag : 'unset' } = { _tag : 'unset' }
164
+ return yield * Effect . sync ( ( ) => {
165
+ const writeTablesForEvent = new Set < string > ( )
166
+
167
+ const exec = ( ) => {
168
+ for ( const {
169
+ statementSql,
170
+ bindValues,
171
+ writeTables = this . sqliteDbWrapper . getTablesUsed ( statementSql ) ,
172
+ } of execArgsArr ) {
173
+ try {
174
+ this . sqliteDbWrapper . cachedExecute ( statementSql , bindValues , { otelContext, writeTables } )
175
+ } catch ( cause ) {
176
+ throw UnexpectedError . make ( {
177
+ cause,
178
+ note : `Error executing materializer for event "${ eventDecoded . name } ".\nStatement: ${ statementSql } \nBind values: ${ JSON . stringify ( bindValues ) } ` ,
179
+ } )
180
+ }
181
+
182
+ // durationMsTotal += durationMs
183
+ for ( const table of writeTables ) {
184
+ writeTablesForEvent . add ( table )
185
+ }
186
+
187
+ this . sqliteDbWrapper . debug . head = eventDecoded . seqNum
188
+ }
189
+ }
188
190
189
- if ( withChangeset === true ) {
190
- sessionChangeset = this . sqliteDbWrapper . withChangeset ( exec ) . changeset
191
- } else {
192
- exec ( )
193
- }
191
+ let sessionChangeset :
192
+ | { _tag : 'sessionChangeset' ; data : Uint8Array ; debug : any }
193
+ | { _tag : 'no-op' }
194
+ | { _tag : 'unset' } = { _tag : 'unset' }
195
+ if ( withChangeset === true ) {
196
+ sessionChangeset = this . sqliteDbWrapper . withChangeset ( exec ) . changeset
197
+ } else {
198
+ exec ( )
199
+ }
194
200
195
- return { writeTables : writeTablesForEvent , sessionChangeset, materializerHash }
196
- } ,
201
+ return { writeTables : writeTablesForEvent , sessionChangeset, materializerHash }
202
+ } )
203
+ } ) ,
204
+ ) ,
197
205
rollback : ( changeset ) => {
198
206
this . sqliteDbWrapper . rollback ( changeset )
199
207
} ,
0 commit comments