diff --git a/.changeset/nasty-sloths-rhyme.md b/.changeset/nasty-sloths-rhyme.md new file mode 100644 index 000000000..2f5b05b43 --- /dev/null +++ b/.changeset/nasty-sloths-rhyme.md @@ -0,0 +1,5 @@ +--- +'@segment/analytics-next': minor +--- + +Fix retry behavior diff --git a/packages/browser/src/plugins/segmentio/__tests__/retries.test.ts b/packages/browser/src/plugins/segmentio/__tests__/retries.test.ts index 5a49e4a7c..c5c002b95 100644 --- a/packages/browser/src/plugins/segmentio/__tests__/retries.test.ts +++ b/packages/browser/src/plugins/segmentio/__tests__/retries.test.ts @@ -21,7 +21,10 @@ describe('Segment.io retries 500s and 429', () => { jest.restoreAllMocks() options = { apiKey: 'foo' } - analytics = new Analytics({ writeKey: options.apiKey }) + analytics = new Analytics( + { writeKey: options.apiKey }, + { retryQueue: true } + ) segment = await segmentio( analytics, options, @@ -36,7 +39,7 @@ describe('Segment.io retries 500s and 429', () => { const ctx = await analytics.track('event') jest.runAllTimers() - expect(ctx.attempts).toBeGreaterThanOrEqual(3) // Gets incremented after use + expect(ctx.attempts).toBeGreaterThanOrEqual(2) // Gets incremented after use expect(fetch.mock.calls.length).toBeGreaterThanOrEqual(2) expect(fetch.mock.lastCall[1].body).toContain('"retryCount":') }) @@ -131,3 +134,57 @@ describe('Batches retry 500s and 429', () => { expect(fetch.mock.lastCall[1].body).toContain('"retryCount":2') }) }) + +describe('retryQueue', () => { + let options: SegmentioSettings + let analytics: Analytics + let segment: Plugin + beforeEach(async () => { + jest.useFakeTimers({ advanceTimers: true }) + jest.resetAllMocks() + jest.restoreAllMocks() + + options = { + apiKey: 'foo', + } + + fetch.mockReturnValue(createError({ status: 500 })) + }) + afterEach(() => { + jest.useRealTimers() + }) + + it('Only attempts once if retryQueue is false', async () => { + analytics = new Analytics( + { writeKey: options.apiKey }, + { retryQueue: false } + ) + segment = await segmentio( + analytics, + options, + cdnSettingsMinimal.integrations + ) + await analytics.register(segment, envEnrichment) + + await analytics.track('foo') + jest.runAllTimers() + expect(fetch).toHaveBeenCalledTimes(1) + }) + + it('Attempts multiple times if retryQueue is true', async () => { + analytics = new Analytics( + { writeKey: options.apiKey }, + { retryQueue: true } + ) + segment = await segmentio( + analytics, + options, + cdnSettingsMinimal.integrations + ) + await analytics.register(segment, envEnrichment) + + await analytics.track('foo') + jest.runAllTimers() + expect(fetch.mock.calls.length).toBeGreaterThanOrEqual(2) + }) +}) diff --git a/packages/browser/src/plugins/segmentio/index.ts b/packages/browser/src/plugins/segmentio/index.ts index f3e40bf26..e05298586 100644 --- a/packages/browser/src/plugins/segmentio/index.ts +++ b/packages/browser/src/plugins/segmentio/index.ts @@ -112,6 +112,11 @@ export function segmentio( json = onAlias(analytics, json) } + if (buffer.getAttempts(ctx) >= buffer.maxAttempts) { + inflightEvents.delete(ctx) + return ctx + } + return client .dispatch( `${remote}/${path}`,