@@ -18,10 +18,10 @@ import { EventProcessor, ProcessableEvent } from "./event_processor";
18
18
import { getBatchedAsync , getBatchedSync , Store } from "../utils/cache/store" ;
19
19
import { EventDispatcher , EventDispatcherResponse , LogEvent } from "./event_dispatcher/event_dispatcher" ;
20
20
import { buildLogEvent } from "./event_builder/log_event" ;
21
- import { BackoffController , ExponentialBackoff , IntervalRepeater , Repeater } from "../utils/repeater/repeater" ;
21
+ import { BackoffController , ExponentialBackoff , Repeater } from "../utils/repeater/repeater" ;
22
22
import { LoggerFacade } from '../logging/logger' ;
23
23
import { BaseService , ServiceState , StartupLog } from "../service" ;
24
- import { Consumer , Fn , Producer } from "../utils/type" ;
24
+ import { Consumer , Fn , Maybe , Producer } from "../utils/type" ;
25
25
import { RunResult , runWithRetry } from "../utils/executor/backoff_retry_runner" ;
26
26
import { isSuccessStatusCode } from "../utils/http_request_handler/http_util" ;
27
27
import { EventEmitter } from "../utils/event_emitter/event_emitter" ;
@@ -31,13 +31,16 @@ import { FAILED_TO_DISPATCH_EVENTS, SERVICE_NOT_RUNNING } from "error_message";
31
31
import { OptimizelyError } from "../error/optimizly_error" ;
32
32
import { sprintf } from "../utils/fns" ;
33
33
import { SERVICE_STOPPED_BEFORE_RUNNING } from "../service" ;
34
+ import { EVENT_STORE_FULL } from "../message/log_message" ;
34
35
35
36
export const DEFAULT_MIN_BACKOFF = 1000 ;
36
37
export const DEFAULT_MAX_BACKOFF = 32000 ;
38
+ export const MAX_EVENTS_IN_STORE = 500 ;
37
39
38
40
export type EventWithId = {
39
41
id : string ;
40
42
event : ProcessableEvent ;
43
+ notStored ?: boolean ;
41
44
} ;
42
45
43
46
export type RetryConfig = {
@@ -59,7 +62,8 @@ export type BatchEventProcessorConfig = {
59
62
60
63
type EventBatch = {
61
64
request : LogEvent ,
62
- ids : string [ ] ,
65
+ // ids: string[],
66
+ events : EventWithId [ ] ,
63
67
}
64
68
65
69
export const LOGGER_NAME = 'BatchEventProcessor' ;
@@ -70,11 +74,13 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
70
74
private eventQueue : EventWithId [ ] = [ ] ;
71
75
private batchSize : number ;
72
76
private eventStore ?: Store < EventWithId > ;
77
+ private eventCountInStore : Maybe < number > = undefined ;
78
+ private maxEventsInStore : number = MAX_EVENTS_IN_STORE ;
73
79
private dispatchRepeater : Repeater ;
74
80
private failedEventRepeater ?: Repeater ;
75
81
private idGenerator : IdGenerator = new IdGenerator ( ) ;
76
82
private runningTask : Map < string , RunResult < EventDispatcherResponse > > = new Map ( ) ;
77
- private dispatchingEventIds : Set < string > = new Set ( ) ;
83
+ private dispatchingEvents : Map < string , EventWithId > = new Map ( ) ;
78
84
private eventEmitter : EventEmitter < { dispatch : LogEvent } > = new EventEmitter ( ) ;
79
85
private retryConfig ?: RetryConfig ;
80
86
@@ -84,11 +90,13 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
84
90
this . closingEventDispatcher = config . closingEventDispatcher ;
85
91
this . batchSize = config . batchSize ;
86
92
this . eventStore = config . eventStore ;
93
+
87
94
this . retryConfig = config . retryConfig ;
88
95
89
96
this . dispatchRepeater = config . dispatchRepeater ;
90
97
this . dispatchRepeater . setTask ( ( ) => this . flush ( ) ) ;
91
98
99
+ this . maxEventsInStore = Math . max ( 2 * config . batchSize , MAX_EVENTS_IN_STORE ) ;
92
100
this . failedEventRepeater = config . failedEventRepeater ;
93
101
this . failedEventRepeater ?. setTask ( ( ) => this . retryFailedEvents ( ) ) ;
94
102
if ( config . logger ) {
@@ -111,7 +119,7 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
111
119
}
112
120
113
121
const keys = ( await this . eventStore . getKeys ( ) ) . filter (
114
- ( k ) => ! this . dispatchingEventIds . has ( k ) && ! this . eventQueue . find ( ( e ) => e . id === k )
122
+ ( k ) => ! this . dispatchingEvents . has ( k ) && ! this . eventQueue . find ( ( e ) => e . id === k )
115
123
) ;
116
124
117
125
const events = await ( this . eventStore . operation === 'sync' ?
@@ -138,7 +146,8 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
138
146
( currentBatch . length > 0 && ! areEventContextsEqual ( currentBatch [ 0 ] . event , event . event ) ) ) {
139
147
batches . push ( {
140
148
request : buildLogEvent ( currentBatch . map ( ( e ) => e . event ) ) ,
141
- ids : currentBatch . map ( ( e ) => e . id ) ,
149
+ // ids: currentBatch.map((e) => e.id),
150
+ events : currentBatch ,
142
151
} ) ;
143
152
currentBatch = [ ] ;
144
153
}
@@ -148,7 +157,8 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
148
157
if ( currentBatch . length > 0 ) {
149
158
batches . push ( {
150
159
request : buildLogEvent ( currentBatch . map ( ( e ) => e . event ) ) ,
151
- ids : currentBatch . map ( ( e ) => e . id ) ,
160
+ // ids: currentBatch.map((e) => e.id),
161
+ events : currentBatch ,
152
162
} ) ;
153
163
}
154
164
@@ -163,15 +173,15 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
163
173
}
164
174
165
175
const events : ProcessableEvent [ ] = [ ] ;
166
- const ids : string [ ] = [ ] ;
176
+ const eventWithIds : EventWithId [ ] = [ ] ;
167
177
168
178
this . eventQueue . forEach ( ( event ) => {
169
179
events . push ( event . event ) ;
170
- ids . push ( event . id ) ;
180
+ eventWithIds . push ( event ) ;
171
181
} ) ;
172
182
173
183
this . eventQueue = [ ] ;
174
- return { request : buildLogEvent ( events ) , ids } ;
184
+ return { request : buildLogEvent ( events ) , events : eventWithIds } ;
175
185
}
176
186
177
187
private async executeDispatch ( request : LogEvent , closing = false ) : Promise < EventDispatcherResponse > {
@@ -185,10 +195,11 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
185
195
}
186
196
187
197
private dispatchBatch ( batch : EventBatch , closing : boolean ) : void {
188
- const { request, ids } = batch ;
198
+ const { request, events } = batch ;
189
199
190
- ids . forEach ( ( id ) => {
191
- this . dispatchingEventIds . add ( id ) ;
200
+ events . forEach ( ( event ) => {
201
+ // this.dispatchingEventIds.add(id);
202
+ this . dispatchingEvents . set ( event . id , event ) ;
192
203
} ) ;
193
204
194
205
const runResult : RunResult < EventDispatcherResponse > = this . retryConfig
@@ -205,9 +216,11 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
205
216
this . runningTask . set ( taskId , runResult ) ;
206
217
207
218
runResult . result . then ( ( res ) => {
208
- ids . forEach ( ( id ) => {
209
- this . dispatchingEventIds . delete ( id ) ;
210
- this . eventStore ?. remove ( id ) ;
219
+ events . forEach ( ( event ) => {
220
+ this . eventStore ?. remove ( event . id ) ;
221
+ if ( ! event . notStored && this . eventCountInStore ) {
222
+ this . eventCountInStore -- ;
223
+ }
211
224
} ) ;
212
225
return Promise . resolve ( ) ;
213
226
} ) . catch ( ( err ) => {
@@ -216,7 +229,7 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
216
229
this . logger ?. error ( err ) ;
217
230
} ) . finally ( ( ) => {
218
231
this . runningTask . delete ( taskId ) ;
219
- ids . forEach ( ( id ) => this . dispatchingEventIds . delete ( id ) ) ;
232
+ events . forEach ( ( event ) => this . dispatchingEvents . delete ( event . id ) ) ;
220
233
} ) ;
221
234
}
222
235
@@ -235,12 +248,12 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
235
248
return Promise . reject ( new OptimizelyError ( SERVICE_NOT_RUNNING , 'BatchEventProcessor' ) ) ;
236
249
}
237
250
238
- const eventWithId = {
251
+ const eventWithId : EventWithId = {
239
252
id : this . idGenerator . getId ( ) ,
240
253
event : event ,
241
254
} ;
242
255
243
- await this . eventStore ?. set ( eventWithId . id , eventWithId ) ;
256
+ await this . storeEvent ( eventWithId ) ;
244
257
245
258
if ( this . eventQueue . length > 0 && ! areEventContextsEqual ( this . eventQueue [ 0 ] . event , event ) ) {
246
259
this . flush ( ) ;
@@ -253,7 +266,35 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
253
266
} else if ( ! this . dispatchRepeater . isRunning ( ) ) {
254
267
this . dispatchRepeater . start ( ) ;
255
268
}
269
+ }
270
+
271
+ private async findEventCountInStore ( ) : Promise < void > {
272
+ if ( this . eventStore && this . eventCountInStore === undefined ) {
273
+ try {
274
+ const keys = await this . eventStore . getKeys ( ) ;
275
+ this . eventCountInStore = keys . length ;
276
+ } catch ( e ) {
277
+ this . logger ?. error ( e ) ;
278
+ }
279
+ }
280
+ }
256
281
282
+ private async storeEvent ( eventWithId : EventWithId ) : Promise < void > {
283
+ await this . findEventCountInStore ( ) ;
284
+ if ( this . eventCountInStore !== undefined && this . eventCountInStore >= this . maxEventsInStore ) {
285
+ this . logger ?. info ( EVENT_STORE_FULL , eventWithId . event . uuid ) ;
286
+ eventWithId . notStored = true ;
287
+ return ;
288
+ }
289
+
290
+ await Promise . resolve ( this . eventStore ?. set ( eventWithId . id , eventWithId ) ) . then ( ( ) => {
291
+ if ( this . eventCountInStore !== undefined ) {
292
+ this . eventCountInStore ++ ;
293
+ }
294
+ } ) . catch ( ( e ) => {
295
+ eventWithId . notStored = true ;
296
+ this . logger ?. error ( e ) ;
297
+ } ) ;
257
298
}
258
299
259
300
start ( ) : void {
0 commit comments