Skip to content

Commit b0a5c8b

Browse files
authored
[FSSDK-9605] add support for configurable closing event dispatcher (#874)
1 parent b1ec8c1 commit b0a5c8b

File tree

5 files changed

+72
-12
lines changed

5 files changed

+72
-12
lines changed

packages/event-processor/__tests__/v1EventProcessor.spec.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,5 +525,41 @@ describe('LogTierV1EventProcessor', () => {
525525
params: makeBatchedEventV1(impressionEvents),
526526
})
527527
})
528+
529+
it('should use the provided closingDispatcher to dispatch events on stop', async () => {
530+
const dispatcher = {
531+
dispatchEvent: jest.fn(),
532+
}
533+
534+
const closingDispatcher = {
535+
dispatchEvent: jest.fn(),
536+
}
537+
538+
const processor = new LogTierV1EventProcessor({
539+
dispatcher,
540+
closingDispatcher,
541+
flushInterval: 100000,
542+
batchSize: 20,
543+
});
544+
545+
processor.start()
546+
547+
const events: ReturnType<typeof createImpressionEvent>[] = [];
548+
549+
for (let i = 0; i < 4; i++) {
550+
const event = createImpressionEvent();
551+
processor.process(event);
552+
events.push(event);
553+
}
554+
555+
processor.stop();
556+
jest.runAllTimers();
557+
558+
expect(dispatcher.dispatchEvent).not.toHaveBeenCalled();
559+
expect(closingDispatcher.dispatchEvent).toHaveBeenCalledTimes(1);
560+
561+
const [data] = closingDispatcher.dispatchEvent.mock.calls[0];
562+
expect(data.params).toEqual(makeBatchedEventV1(events));
563+
})
528564
})
529565
})

packages/event-processor/src/eventProcessor.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2019-2020, Optimizely
2+
* Copyright 2019-2020, 2023 Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
1717
import { Managed } from './managed'
1818
import { ConversionEvent, ImpressionEvent } from './events'
1919
import { EventV1Request } from './eventDispatcher'
20-
import { EventQueue, DefaultEventQueue, SingleEventQueue } from './eventQueue'
20+
import { EventQueue, DefaultEventQueue, SingleEventQueue, EventQueueSink } from './eventQueue'
2121
import { getLogger } from '@optimizely/js-sdk-logging'
2222
import { NOTIFICATION_TYPES, NotificationCenter } from '@optimizely/js-sdk-utils'
2323

@@ -56,14 +56,21 @@ export function validateAndGetBatchSize(batchSize: number): number {
5656
return batchSize
5757
}
5858

59-
export function getQueue(batchSize: number, flushInterval: number, sink: any, batchComparator: any): EventQueue<ProcessableEvent> {
59+
export function getQueue(
60+
batchSize: number,
61+
flushInterval: number,
62+
batchComparator: any,
63+
sink: EventQueueSink<ProcessableEvent>,
64+
closingSink?: EventQueueSink<ProcessableEvent>,
65+
): EventQueue<ProcessableEvent> {
6066
let queue: EventQueue<ProcessableEvent>
6167
if (batchSize > 1) {
6268
queue = new DefaultEventQueue<ProcessableEvent>({
6369
flushInterval,
6470
maxQueueSize: batchSize,
65-
sink,
6671
batchComparator,
72+
sink,
73+
closingSink,
6774
})
6875
} else {
6976
queue = new SingleEventQueue({ sink })

packages/event-processor/src/eventQueue.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2019, Optimizely
2+
* Copyright 2019, 2023 Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -87,6 +87,7 @@ export class DefaultEventQueue<K> implements EventQueue<K> {
8787
private buffer: K[]
8888
private maxQueueSize: number
8989
private sink: EventQueueSink<K>
90+
private closingSink?: EventQueueSink<K>
9091
// batchComparator is called to determine whether two events can be included
9192
// together in the same batch
9293
private batchComparator: (eventA: K, eventB: K) => boolean
@@ -96,16 +97,19 @@ export class DefaultEventQueue<K> implements EventQueue<K> {
9697
flushInterval,
9798
maxQueueSize,
9899
sink,
100+
closingSink,
99101
batchComparator,
100102
}: {
101103
flushInterval: number
102104
maxQueueSize: number
103105
sink: EventQueueSink<K>
106+
closingSink?: EventQueueSink<K>
104107
batchComparator: (eventA: K, eventB: K) => boolean
105108
}) {
106109
this.buffer = []
107110
this.maxQueueSize = Math.max(maxQueueSize, 1)
108111
this.sink = sink
112+
this.closingSink = closingSink;
109113
this.batchComparator = batchComparator
110114
this.timer = new Timer({
111115
callback: this.flush.bind(this),
@@ -121,7 +125,7 @@ export class DefaultEventQueue<K> implements EventQueue<K> {
121125

122126
stop(): Promise<any> {
123127
this.started = false
124-
const result = this.sink(this.buffer)
128+
const result = this.closingSink ? this.closingSink(this.buffer) : this.sink(this.buffer);
125129
this.buffer = []
126130
this.timer.stop()
127131
return result

packages/event-processor/src/v1/v1EventProcessor.react_native.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2020, Optimizely
2+
* Copyright 2020, 2023, Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -102,7 +102,7 @@ export class LogTierV1EventProcessor implements EventProcessor {
102102

103103
flushInterval = validateAndGetFlushInterval(flushInterval)
104104
batchSize = validateAndGetBatchSize(batchSize)
105-
this.queue = getQueue(batchSize, flushInterval, this.drainQueue.bind(this), areEventContextsEqual)
105+
this.queue = getQueue(batchSize, flushInterval, areEventContextsEqual, this.drainQueue.bind(this))
106106
this.pendingEventsStore = new ReactNativeEventsStore(maxQueueSize, PENDING_EVENTS_STORE_KEY)
107107
this.eventBufferStore = new ReactNativeEventsStore(maxQueueSize, EVENT_BUFFER_STORE_KEY)
108108
}

packages/event-processor/src/v1/v1EventProcessor.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2019-2020, Optimizely
2+
* Copyright 2019-2020, 2023 Optimizely
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,31 +36,41 @@ const logger = getLogger('LogTierV1EventProcessor')
3636

3737
export class LogTierV1EventProcessor implements EventProcessor {
3838
private dispatcher: EventDispatcher
39+
private closingDispatcher?: EventDispatcher
3940
private queue: EventQueue<ProcessableEvent>
4041
private notificationCenter?: NotificationCenter
4142
private requestTracker: RequestTracker
4243

4344
constructor({
4445
dispatcher,
46+
closingDispatcher,
4547
flushInterval = DEFAULT_FLUSH_INTERVAL,
4648
batchSize = DEFAULT_BATCH_SIZE,
4749
notificationCenter,
4850
}: {
4951
dispatcher: EventDispatcher
52+
closingDispatcher?: EventDispatcher
5053
flushInterval?: number
5154
batchSize?: number
5255
notificationCenter?: NotificationCenter
5356
}) {
5457
this.dispatcher = dispatcher
58+
this.closingDispatcher = closingDispatcher
5559
this.notificationCenter = notificationCenter
5660
this.requestTracker = new RequestTracker()
5761

5862
flushInterval = validateAndGetFlushInterval(flushInterval)
5963
batchSize = validateAndGetBatchSize(batchSize)
60-
this.queue = getQueue(batchSize, flushInterval, this.drainQueue.bind(this), areEventContextsEqual)
64+
this.queue = getQueue(
65+
batchSize,
66+
flushInterval,
67+
areEventContextsEqual,
68+
this.drainQueue.bind(this, false),
69+
this.drainQueue.bind(this, true),
70+
)
6171
}
6272

63-
drainQueue(buffer: ProcessableEvent[]): Promise<void> {
73+
private drainQueue(useClosingDispatcher: boolean, buffer: ProcessableEvent[]): Promise<void> {
6474
const reqPromise = new Promise<void>(resolve => {
6575
logger.debug('draining queue with %s events', buffer.length)
6676

@@ -70,7 +80,10 @@ export class LogTierV1EventProcessor implements EventProcessor {
7080
}
7181

7282
const formattedEvent = formatEvents(buffer)
73-
this.dispatcher.dispatchEvent(formattedEvent, () => {
83+
const dispatcher = useClosingDispatcher && this.closingDispatcher
84+
? this.closingDispatcher : this.dispatcher;
85+
86+
dispatcher.dispatchEvent(formattedEvent, () => {
7487
resolve()
7588
})
7689
sendEventNotification(this.notificationCenter, formattedEvent)

0 commit comments

Comments
 (0)