Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
091aaf2
first implementation of offline events. Need to do code cleanup
zashraf1985 Jul 2, 2020
8076ef4
added new `eventMaxQueueSize` configuration option.
zashraf1985 Jul 3, 2020
6d338d2
some cleanup and refactor
zashraf1985 Jul 3, 2020
ab29e0e
added some comments
zashraf1985 Jul 3, 2020
cbb6aef
added connectivity listener
zashraf1985 Jul 4, 2020
b26d407
fixed existing unit tests
zashraf1985 Jul 6, 2020
edbfaba
Merge branch 'master' into zeeshan/rn-event-processor-proto
zashraf1985 Jul 6, 2020
0621882
sequences the pending events one after the other
zashraf1985 Jul 8, 2020
e94ebdc
Sequenced the buffered events after pending events on the start
zashraf1985 Jul 8, 2020
35b5d4f
added some extra checks to fix the behavior of stop
zashraf1985 Jul 9, 2020
7db47a6
modified the resolvable promise to make it work with jest
zashraf1985 Jul 9, 2020
d99fb66
1. added await while clearing buffer store
zashraf1985 Jul 9, 2020
9918024
re factored the hierarchy of event processor classes
zashraf1985 Jul 10, 2020
8018de0
refactored how pending events are dispatched. simplified the whole ev…
zashraf1985 Jul 10, 2020
134c5df
removed localhost url
zashraf1985 Jul 10, 2020
8467a91
fixed existing unit tests
zashraf1985 Jul 10, 2020
a49a6fa
renamed file to reflect its react native version of event processor
zashraf1985 Jul 10, 2020
a19f66f
simplified synchronizer
zashraf1985 Jul 13, 2020
bb7024e
using only one store for both pending events and events buffer
zashraf1985 Jul 13, 2020
01ef03e
Update packages/event-processor/src/v1/v1EventProcessor.react_native.ts
zashraf1985 Jul 13, 2020
3411d52
added some logs
zashraf1985 Jul 14, 2020
108fea6
Added unit tests for React Native store
zashraf1985 Jul 14, 2020
8dadf85
incorporated review feedback from jae and owais
zashraf1985 Jul 16, 2020
b5267fb
Added skeleton for react native event processor unit tests. Its not c…
zashraf1985 Jul 16, 2020
6c3c40d
moved cache code from utils to this repo to resolve dependency issues
zashraf1985 Jul 17, 2020
a028ffd
added unit tests and fixed some issues found during unit testing
zashraf1985 Jul 17, 2020
b92d95d
added more test and fixed an issue with buffer store
zashraf1985 Jul 18, 2020
2b1594d
added more tests
zashraf1985 Jul 19, 2020
dd7c837
reduced timeouts to make tests faster
zashraf1985 Jul 19, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions packages/event-processor/__tests__/v1EventProcessor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ describe('LogTierV1EventProcessor', () => {
stubDispatcher = {
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void {
dispatchStub(event)
callback(200)
callback({ statusCode: 200 })
},
}
})
Expand Down Expand Up @@ -161,7 +161,7 @@ describe('LogTierV1EventProcessor', () => {
done()
})

localCallback(200)
localCallback({ statusCode: 200 })
})

it('should return a promise that is resolved when the dispatcher callback returns a 400 response', done => {
Expand Down Expand Up @@ -198,7 +198,7 @@ describe('LogTierV1EventProcessor', () => {
stubDispatcher = {
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void {
dispatchStub(event)
callback(200)
callback({ statusCode: 200 })
},
}

Expand All @@ -224,7 +224,7 @@ describe('LogTierV1EventProcessor', () => {
it('should stop accepting events after stop is called', () => {
const dispatcher = {
dispatchEvent: jest.fn((event: EventV1Request, callback: EventDispatcherCallback) => {
setTimeout(() => callback(204), 0)
setTimeout(() => callback({ statusCode: 204 }), 0)
})
}
const processor = new LogTierV1EventProcessor({
Expand Down Expand Up @@ -282,10 +282,10 @@ describe('LogTierV1EventProcessor', () => {
})
expect(stopPromiseResolved).toBe(false)

dispatchCbs[0](204)
dispatchCbs[0]({ statusCode: 204 })
jest.advanceTimersByTime(100)
expect(stopPromiseResolved).toBe(false)
dispatchCbs[1](204)
dispatchCbs[1]({ statusCode: 204 })
await stopPromise
expect(stopPromiseResolved).toBe(true)
})
Expand Down
6 changes: 5 additions & 1 deletion packages/event-processor/src/eventDispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
*/
import { EventV1 } from "./v1/buildEventV1";

export type EventDispatcherCallback = (status: number) => void
export type EventDispatcherResponse = {
statusCode: number
}

export type EventDispatcherCallback = (response: EventDispatcherResponse) => void

export interface EventDispatcher {
dispatchEvent(event: EventV1Request, callback: EventDispatcherCallback): void
Expand Down
147 changes: 45 additions & 102 deletions packages/event-processor/src/eventProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,124 +15,67 @@
*/
// TODO change this to use Managed from js-sdk-models when available
import { Managed } from './managed'
import { ConversionEvent, ImpressionEvent, areEventContextsEqual } from './events'
import { EventDispatcher, EventV1Request } from './eventDispatcher'
import { ConversionEvent, ImpressionEvent } from './events'
import { EventV1Request } from './eventDispatcher'
import { EventQueue, DefaultEventQueue, SingleEventQueue } from './eventQueue'
import { getLogger } from '@optimizely/js-sdk-logging'
import { NOTIFICATION_TYPES, NotificationCenter } from '@optimizely/js-sdk-utils'
import RequestTracker from './requestTracker';

const logger = getLogger('EventProcessor')

export type ProcessableEvents = ConversionEvent | ImpressionEvent

export type EventDispatchResult = { result: boolean; event: ProcessableEvents }

export interface EventProcessor extends Managed {
process(event: ProcessableEvents): void
}

const DEFAULT_FLUSH_INTERVAL = 30000 // Unit is ms - default flush interval is 30s
const DEFAULT_BATCH_SIZE = 10

export abstract class AbstractEventProcessor implements EventProcessor {
protected dispatcher: EventDispatcher
protected queue: EventQueue<ProcessableEvents>
private notificationCenter?: NotificationCenter
protected requestTracker: RequestTracker

constructor({
dispatcher,
flushInterval = 30000,
batchSize = 3000,
notificationCenter,
}: {
dispatcher: EventDispatcher
flushInterval?: number
batchSize?: number
notificationCenter?: NotificationCenter
}) {
this.dispatcher = dispatcher

if (flushInterval <= 0) {
logger.warn(
`Invalid flushInterval ${flushInterval}, defaulting to ${DEFAULT_FLUSH_INTERVAL}`,
)
flushInterval = DEFAULT_FLUSH_INTERVAL
}

batchSize = Math.floor(batchSize)
if (batchSize < 1) {
logger.warn(
`Invalid batchSize ${batchSize}, defaulting to ${DEFAULT_BATCH_SIZE}`,
)
batchSize = DEFAULT_BATCH_SIZE
}

batchSize = Math.max(1, batchSize)
if (batchSize > 1) {
this.queue = new DefaultEventQueue<ProcessableEvents>({
flushInterval,
maxQueueSize: batchSize,
sink: buffer => this.drainQueue(buffer),
batchComparator: areEventContextsEqual,
})
} else {
this.queue = new SingleEventQueue({
sink: buffer => this.drainQueue(buffer),
})
}
this.notificationCenter = notificationCenter

this.requestTracker = new RequestTracker()
}
const logger = getLogger('EventProcessor')

drainQueue(buffer: ProcessableEvents[]): Promise<void> {
const reqPromise = new Promise<void>(resolve => {
logger.debug('draining queue with %s events', buffer.length)
export type ProcessableEvent = ConversionEvent | ImpressionEvent

if (buffer.length === 0) {
resolve()
return
}
export type EventDispatchResult = { result: boolean; event: ProcessableEvent }

const formattedEvent = this.formatEvents(buffer)
this.dispatcher.dispatchEvent(formattedEvent, () => {
resolve()
})
this.sendEventNotification(formattedEvent)
})
this.requestTracker.trackRequest(reqPromise)
return reqPromise
}
export interface EventProcessor extends Managed {
process(event: ProcessableEvent): void
}

protected sendEventNotification(event: EventV1Request): void {
if (this.notificationCenter) {
this.notificationCenter.sendNotifications(
NOTIFICATION_TYPES.LOG_EVENT,
event,
)
}
export function validateAndGetFlushInterval(flushInterval: number): number {
if (flushInterval <= 0) {
logger.warn(
`Invalid flushInterval ${flushInterval}, defaulting to ${DEFAULT_FLUSH_INTERVAL}`,
)
flushInterval = DEFAULT_FLUSH_INTERVAL
}
return flushInterval
}

process(event: ProcessableEvents): void {
this.queue.enqueue(event)
export function validateAndGetBatchSize(batchSize: number): number {
batchSize = Math.floor(batchSize)
if (batchSize < 1) {
logger.warn(
`Invalid batchSize ${batchSize}, defaulting to ${DEFAULT_BATCH_SIZE}`,
)
batchSize = DEFAULT_BATCH_SIZE
}
batchSize = Math.max(1, batchSize)
return batchSize
}

stop(): Promise<any> {
// swallow - an error stopping this queue shouldn't prevent this from stopping
try {
this.queue.stop()
return this.requestTracker.onRequestsComplete()
} catch (e) {
logger.error('Error stopping EventProcessor: "%s"', e.message, e)
}
return Promise.resolve()
export function getQueue(batchSize: number, flushInterval: number, sink: any, batchComparator: any): EventQueue<ProcessableEvent> {
let queue: EventQueue<ProcessableEvent>
if (batchSize > 1) {
queue = new DefaultEventQueue<ProcessableEvent>({
flushInterval,
maxQueueSize: batchSize,
sink,
batchComparator,
})
} else {
queue = new SingleEventQueue({ sink })
}
return queue
}

start(): void {
this.queue.start()
export function sendEventNotification(notificationCenter: NotificationCenter | undefined, event: EventV1Request): void {
if (notificationCenter) {
notificationCenter.sendNotifications(
NOTIFICATION_TYPES.LOG_EVENT,
event,
)
}

protected abstract formatEvents(events: ProcessableEvents[]): EventV1Request
}
2 changes: 1 addition & 1 deletion packages/event-processor/src/index.react_native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ export * from './eventDispatcher'
export * from './managed'
export * from './pendingEventsDispatcher'
export * from './v1/buildEventV1'
export { LogTierV1ReactNativeEventProcessor as LogTierV1EventProcessor } from './v1/v1EventProcessor'
export * from './v1/v1EventProcessor.react_native'
2 changes: 1 addition & 1 deletion packages/event-processor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ export * from './eventDispatcher'
export * from './managed'
export * from './pendingEventsDispatcher'
export * from './v1/buildEventV1'
export { LogTierV1EventProcessor } from './v1/v1EventProcessor'
export * from './v1/v1EventProcessor'
Loading