diff --git a/lib/event_processor/batch_event_processor.spec.ts b/lib/event_processor/batch_event_processor.spec.ts index f89f9b5ef..a95dd262f 100644 --- a/lib/event_processor/batch_event_processor.spec.ts +++ b/lib/event_processor/batch_event_processor.spec.ts @@ -1,5 +1,5 @@ /** - * Copyright 2024, Optimizely + * Copyright 2024-2025, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -639,53 +639,6 @@ describe('BatchEventProcessor', async () => { } }); - it('should retry indefinitely using the provided backoffController if maxRetry is undefined', async () => { - const eventDispatcher = getMockDispatcher(); - const mockDispatch: MockInstance = eventDispatcher.dispatchEvent; - mockDispatch.mockRejectedValue(new Error()); - const dispatchRepeater = getMockRepeater(); - - const backoffController = { - backoff: vi.fn().mockReturnValue(1000), - reset: vi.fn(), - }; - - const processor = new BatchEventProcessor({ - eventDispatcher, - dispatchRepeater, - retryConfig: { - backoffProvider: () => backoffController, - }, - batchSize: 100, - }); - - processor.start(); - await processor.onRunning(); - - const events: ProcessableEvent[] = []; - for(let i = 0; i < 10; i++) { - const event = createImpressionEvent(`id-${i}`); - events.push(event); - await processor.process(event); - } - - expect(eventDispatcher.dispatchEvent).toHaveBeenCalledTimes(0); - await dispatchRepeater.execute(0); - - for(let i = 0; i < 200; i++) { - await exhaustMicrotasks(); - await advanceTimersByTime(1000); - } - - expect(eventDispatcher.dispatchEvent).toHaveBeenCalledTimes(201); - expect(backoffController.backoff).toHaveBeenCalledTimes(200); - - const request = buildLogEvent(events); - for(let i = 0; i < 201; i++) { - expect(eventDispatcher.dispatchEvent.mock.calls[i][0]).toEqual(request); - } - }); - it('should remove the events from the eventStore after dispatch is successfull', async () => { const eventDispatcher = getMockDispatcher(); const mockDispatch: MockInstance = eventDispatcher.dispatchEvent; diff --git a/lib/event_processor/batch_event_processor.ts b/lib/event_processor/batch_event_processor.ts index bf0ed3f39..48ce32927 100644 --- a/lib/event_processor/batch_event_processor.ts +++ b/lib/event_processor/batch_event_processor.ts @@ -44,7 +44,7 @@ export type EventWithId = { }; export type RetryConfig = { - maxRetries?: number; + maxRetries: number; backoffProvider: Producer; } diff --git a/lib/event_processor/event_processor_factory.node.spec.ts b/lib/event_processor/event_processor_factory.node.spec.ts index 43d65ee44..512865381 100644 --- a/lib/event_processor/event_processor_factory.node.spec.ts +++ b/lib/event_processor/event_processor_factory.node.spec.ts @@ -187,10 +187,10 @@ describe('createBatchEventProcessor', () => { expect(mockGetOpaqueBatchEventProcessor.mock.calls[1][0].batchSize).toBe(undefined); }); - it('uses maxRetries value of 10', () => { + it('uses maxRetries value of 5', () => { const processor = createBatchEventProcessor({ }); expect(Object.is(processor, mockGetOpaqueBatchEventProcessor.mock.results[0].value)).toBe(true); - expect(mockGetOpaqueBatchEventProcessor.mock.calls[0][0].retryOptions?.maxRetries).toBe(10); + expect(mockGetOpaqueBatchEventProcessor.mock.calls[0][0].retryOptions?.maxRetries).toBe(5); }); it('uses no failed event retry if an eventStore is not provided', () => { diff --git a/lib/event_processor/event_processor_factory.node.ts b/lib/event_processor/event_processor_factory.node.ts index 6ef10be9f..cdcb533a1 100644 --- a/lib/event_processor/event_processor_factory.node.ts +++ b/lib/event_processor/event_processor_factory.node.ts @@ -47,7 +47,8 @@ export const createBatchEventProcessor = ( defaultFlushInterval: DEFAULT_EVENT_FLUSH_INTERVAL, defaultBatchSize: DEFAULT_EVENT_BATCH_SIZE, retryOptions: { - maxRetries: 10, + maxRetries: 5, + }, failedEventRetryInterval: eventStore ? FAILED_EVENT_RETRY_INTERVAL : undefined, eventStore, diff --git a/lib/event_processor/event_processor_factory.spec.ts b/lib/event_processor/event_processor_factory.spec.ts index c0ea8cb5a..fc57a5097 100644 --- a/lib/event_processor/event_processor_factory.spec.ts +++ b/lib/event_processor/event_processor_factory.spec.ts @@ -1,5 +1,5 @@ /** - * Copyright 2024, Optimizely + * Copyright 2024-2025, Optimizely * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,24 +83,8 @@ describe('getBatchEventProcessor', () => { expect(MockBatchEventProcessor.mock.calls[0][0].retryConfig).toBe(undefined); }); - it('uses retry when retryOptions is provided', () => { - const options = { - eventDispatcher: getMockEventDispatcher(), - retryOptions: {}, - defaultFlushInterval: 1000, - defaultBatchSize: 10, - }; - - const processor = getBatchEventProcessor(options); - - expect(Object.is(processor, MockBatchEventProcessor.mock.instances[0])).toBe(true); - const usedRetryConfig = MockBatchEventProcessor.mock.calls[0][0].retryConfig; - expect(usedRetryConfig).not.toBe(undefined); - expect(usedRetryConfig?.backoffProvider).not.toBe(undefined); - }); - it('uses the correct maxRetries value when retryOptions is provided', () => { - const options1 = { + const options = { eventDispatcher: getMockEventDispatcher(), defaultFlushInterval: 1000, defaultBatchSize: 10, @@ -109,21 +93,9 @@ describe('getBatchEventProcessor', () => { }, }; - const processor1 = getBatchEventProcessor(options1); - expect(Object.is(processor1, MockBatchEventProcessor.mock.instances[0])).toBe(true); + const processor = getBatchEventProcessor(options); + expect(Object.is(processor, MockBatchEventProcessor.mock.instances[0])).toBe(true); expect(MockBatchEventProcessor.mock.calls[0][0].retryConfig?.maxRetries).toBe(10); - - const options2 = { - eventDispatcher: getMockEventDispatcher(), - defaultFlushInterval: 1000, - defaultBatchSize: 10, - retryOptions: {}, - }; - - const processor2 = getBatchEventProcessor(options2); - expect(Object.is(processor2, MockBatchEventProcessor.mock.instances[1])).toBe(true); - expect(MockBatchEventProcessor.mock.calls[0][0].retryConfig).not.toBe(undefined); - expect(MockBatchEventProcessor.mock.calls[1][0].retryConfig?.maxRetries).toBe(undefined); }); it('uses exponential backoff with default parameters when retryOptions is provided without backoff values', () => { @@ -131,12 +103,14 @@ describe('getBatchEventProcessor', () => { eventDispatcher: getMockEventDispatcher(), defaultFlushInterval: 1000, defaultBatchSize: 10, - retryOptions: {}, + retryOptions: { maxRetries: 2 }, }; const processor = getBatchEventProcessor(options); expect(Object.is(processor, MockBatchEventProcessor.mock.instances[0])).toBe(true); + expect(MockBatchEventProcessor.mock.calls[0][0].retryConfig?.maxRetries).toBe(2); + const backoffProvider = MockBatchEventProcessor.mock.calls[0][0].retryConfig?.backoffProvider; expect(backoffProvider).not.toBe(undefined); const backoff = backoffProvider?.(); @@ -149,11 +123,14 @@ describe('getBatchEventProcessor', () => { eventDispatcher: getMockEventDispatcher(), defaultFlushInterval: 1000, defaultBatchSize: 10, - retryOptions: { minBackoff: 1000, maxBackoff: 2000 }, + retryOptions: { maxRetries: 2, minBackoff: 1000, maxBackoff: 2000 }, }; const processor = getBatchEventProcessor(options); expect(Object.is(processor, MockBatchEventProcessor.mock.instances[0])).toBe(true); + + expect(MockBatchEventProcessor.mock.calls[0][0].retryConfig?.maxRetries).toBe(2); + const backoffProvider = MockBatchEventProcessor.mock.calls[0][0].retryConfig?.backoffProvider; expect(backoffProvider).not.toBe(undefined); diff --git a/lib/event_processor/event_processor_factory.ts b/lib/event_processor/event_processor_factory.ts index e931d5b1f..3fff90c9f 100644 --- a/lib/event_processor/event_processor_factory.ts +++ b/lib/event_processor/event_processor_factory.ts @@ -66,7 +66,7 @@ export type BatchEventProcessorFactoryOptions = Omit; retryOptions?: { - maxRetries?: number; + maxRetries: number; minBackoff?: number; maxBackoff?: number; };