11import { Worker , MessageChannel } from 'node:worker_threads' ;
22import type {
3- IEvent , IEventStorageReader , IEventStore , IExtendableLogger , ILogger , IViewLocker
3+ IEvent ,
4+ IEventSet ,
5+ IEventStorageReader ,
6+ IEventStore ,
7+ IExtendableLogger ,
8+ ILogger ,
9+ IViewLocker
410} from '../interfaces/index.ts' ;
511import type { IProxyProjection , IWorkerProjection , ProxyProjectionParams } from './interfaces/index.ts' ;
612import * as Comlink from 'comlink' ;
@@ -18,6 +24,8 @@ export class WorkerProxyProjection<
1824 TProjection extends IWorkerProjection < TView > = IWorkerProjection < TView >
1925> implements IProxyProjection < TView > {
2026
27+ static RESTORE_BATCH_SIZE = 5_000 ;
28+
2129 #worker?: Worker ;
2230 readonly #workerInit: Promise < Worker > ;
2331 readonly #remoteProjection: Comlink . Remote < TProjection > ;
@@ -83,7 +91,12 @@ export class WorkerProxyProjection<
8391 this . viewLocker . unlock ( ) ;
8492 }
8593
86- /** Restore view state from not-yet-projected events */
94+ /**
95+ * Restore view state from not-yet-projected events.
96+ *
97+ * Events are projected in batches to reduce worker RPC overhead.
98+ * The batch size can be configured through {@link WorkerProxyProjection.RESTORE_BATCH_SIZE}.
99+ */
87100 protected async _restore ( eventStore : IEventStorageReader ) : Promise < void > {
88101 if ( ! this . #worker)
89102 await this . #workerInit;
@@ -92,17 +105,25 @@ export class WorkerProxyProjection<
92105 const lastEvent = await this . #remoteProjection. getLastProjectedEvent ( ) ;
93106
94107 this . #logger?. debug ( `retrieving ${ lastEvent ? `events after ${ describe ( lastEvent ) } ` : 'all events' } ...` ) ;
95-
96108 const eventsIterable = eventStore . getEventsByTypes ( this . #messageTypes, { afterEvent : lastEvent } ) ;
97109
98110 let eventsCount = 0 ;
99111 const startTs = Date . now ( ) ;
112+ const batch : IEvent [ ] = [ ] ;
100113
101114 for await ( const event of eventsIterable ) {
102- await this . _project ( event ) ;
115+ batch . push ( event ) ;
103116 eventsCount += 1 ;
117+
118+ if ( batch . length >= WorkerProxyProjection . RESTORE_BATCH_SIZE ) {
119+ await this . _projectBatch ( batch ) ;
120+ batch . length = 0 ;
121+ }
104122 }
105123
124+ if ( batch . length )
125+ await this . _projectBatch ( batch ) ;
126+
106127 this . #logger?. info ( `view restored from ${ eventsCount } event(s) in ${ Date . now ( ) - startTs } ms` ) ;
107128 }
108129
@@ -134,8 +155,8 @@ export class WorkerProxyProjection<
134155 return this . #remoteProjection. project ( event ) ;
135156 }
136157
137- protected async _project ( event : IEvent ) : Promise < void > {
138- await this . # remoteProjection. _project ( event ) ;
158+ protected _projectBatch ( batch : IEventSet ) : Promise < void > {
159+ return this . remoteProjection . _projectBatch ( batch ) ;
139160 }
140161
141162 dispose ( ) {
0 commit comments