Skip to content

Commit 391c74a

Browse files
fix: clear analytics queue on callback errors (#8934)
## Explanation Clear persisted analytics queue entries once the platform adapter delivery callback fires, even when the callback receives an error. This aligns queue cleanup behavior with the previous Segment-backed MetaMetrics flow and avoids repeatedly replaying malformed or permanently failing events on restart. ## References NA For example: * Needed for MetaMask/MetaMask-planning#7193 ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md) - [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes when persisted analytics events are dropped versus retried; events reported as failed by the adapter will not be re-sent after restart, which is intentional but affects delivery reliability semantics. > > **Overview** > When persisted event-queue delivery runs, **`AnalyticsController` now removes queued entries as soon as the platform adapter’s delivery callback fires**, including when the callback passes an error. Failed deliveries are still logged; the queue is no longer left intact for those cases. > > That matches prior Segment-backed MetaMetrics behavior and stops **replaying events that already failed delivery** (for example malformed or permanently rejected payloads) on the next startup. **Queued items are still retained if the adapter throws synchronously** before the callback runs. > > Tests and the package changelog were updated for the new cleanup behavior. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 18ab987. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent a565632 commit 391c74a

3 files changed

Lines changed: 7 additions & 14 deletions

File tree

packages/analytics-controller/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- Clear persisted analytics event queue entries after the delivery callback runs, including when the callback reports an error. ([#8934](https://github.com/MetaMask/core/pull/8934))
13+
1014
## [1.1.0]
1115

1216
### Added

packages/analytics-controller/src/AnalyticsController.test.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,7 +1301,7 @@ describe('AnalyticsController', () => {
13011301
expect(controller.state.eventQueue).toStrictEqual({});
13021302
});
13031303

1304-
it('keeps queued payloads when the adapter callback receives an error', async () => {
1304+
it('clears queued payloads when the adapter callback receives an error', async () => {
13051305
const mockAdapter = createMockAdapter();
13061306
const { controller } = await setupController({
13071307
state: {
@@ -1317,14 +1317,7 @@ describe('AnalyticsController', () => {
13171317
const deliveryOptions = getDeliveryOptions(mockAdapter.track);
13181318
deliveryOptions.callback?.(new Error('Segment failed'));
13191319

1320-
const [messageId] = Object.keys(controller.state.eventQueue ?? {});
1321-
1322-
expect(controller.state.eventQueue).toHaveProperty(messageId);
1323-
expect(controller.state.eventQueue?.[messageId]).toMatchObject({
1324-
type: 'track',
1325-
eventName: 'test_event',
1326-
properties: { prop: 'value' },
1327-
});
1320+
expect(controller.state.eventQueue).toStrictEqual({});
13281321
});
13291322

13301323
it('keeps queued payloads when the platform adapter throws', async () => {
@@ -1360,17 +1353,14 @@ describe('AnalyticsController', () => {
13601353
let adapterMutationCompleted = false;
13611354
jest
13621355
.spyOn(mockAdapter, 'track')
1363-
.mockImplementation((_eventName, properties, context, options) => {
1356+
.mockImplementation((_eventName, properties, context) => {
13641357
(
13651358
properties as { nested: { adapterNormalized?: boolean } }
13661359
).nested.adapterNormalized = true;
13671360
(
13681361
context as { page: { adapterNormalized?: boolean } }
13691362
).page.adapterNormalized = true;
13701363
adapterMutationCompleted = true;
1371-
(options as AnalyticsDeliveryOptions).callback?.(
1372-
new Error('Segment failed'),
1373-
);
13741364
});
13751365
const { controller } = await setupController({
13761366
state: {

packages/analytics-controller/src/AnalyticsController.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,6 @@ export class AnalyticsController extends BaseController<
555555
messageId: queuedEvent.messageId,
556556
error,
557557
});
558-
return;
559558
}
560559

561560
this.#removeQueuedEvent(queuedEvent.messageId);

0 commit comments

Comments
 (0)