Skip to content

Commit 87e4cb4

Browse files
authored
feat: keep alive when dispatch fails (#524)
* feat: disableOnFail * doc: add config doc * Revert "doc: add config doc" This reverts commit ec1f74f. * Revert "feat: disableOnFail" This reverts commit 67ed7b3. * feat: only disable RUM when dispatch fails with 403 or 404 * chore: add unit tests * feat: add 401
1 parent c2573a7 commit 87e4cb4

File tree

2 files changed

+135
-14
lines changed

2 files changed

+135
-14
lines changed

src/dispatch/Dispatch.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class Dispatch {
3838
private dispatchTimerId: number | undefined;
3939
private buildClient: ClientBuilder;
4040
private config: Config;
41+
private disableCodes = ['401', '403', '404'];
4142

4243
constructor(
4344
region: string,
@@ -232,10 +233,12 @@ export class Dispatch {
232233
}
233234

234235
private handleReject = (e: any): { response: HttpResponse } => {
235-
// The handler has run out of retries. We adhere to our convention to
236-
// fail safe by disabling dispatch. This ensures that we will not
237-
// continue to attempt requests when the problem is not recoverable.
238-
this.disable();
236+
if (e instanceof Error && this.disableCodes.includes(e.message)) {
237+
// RUM disables only when dispatch fails and we are certain
238+
// that subsequent attempts will not succeed, such as when
239+
// credentials are invalid or the app monitor does not exist.
240+
this.disable();
241+
}
239242
throw e;
240243
};
241244

src/dispatch/__tests__/Dispatch.test.ts

Lines changed: 128 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -419,15 +419,41 @@ describe('Dispatch tests', () => {
419419
);
420420
});
421421

422-
test('when a fetch request is rejected then dispatch is disabled', async () => {
422+
test('when a fetch request is rejected with 429 then dispatch is NOT disabled', async () => {
423423
// Init
424-
const ERROR = 'Something went wrong.';
425-
const sendFetch = jest.fn(() => Promise.reject(ERROR));
426-
(DataPlaneClient as any).mockImplementation(() => {
427-
return {
428-
sendFetch
429-
};
430-
});
424+
(DataPlaneClient as any).mockImplementationOnce(() => ({
425+
sendFetch: () => Promise.reject(new Error('429'))
426+
}));
427+
428+
const eventCache: EventCache =
429+
Utils.createDefaultEventCacheWithEvents();
430+
431+
const dispatch = new Dispatch(
432+
Utils.AWS_RUM_REGION,
433+
Utils.AWS_RUM_ENDPOINT,
434+
eventCache,
435+
{
436+
...DEFAULT_CONFIG,
437+
...{ dispatchInterval: Utils.AUTO_DISPATCH_OFF, retries: 0 }
438+
}
439+
);
440+
dispatch.setAwsCredentials(Utils.createAwsCredentials());
441+
442+
// Run
443+
eventCache.recordEvent('com.amazon.rum.event1', {});
444+
445+
// Assert
446+
await expect(dispatch.dispatchFetch()).rejects.toEqual(
447+
new Error('429')
448+
);
449+
expect((dispatch as unknown as any).enabled).toBe(true);
450+
});
451+
452+
test('when a fetch request is rejected with 500 then dispatch is NOT disabled', async () => {
453+
// Init
454+
(DataPlaneClient as any).mockImplementationOnce(() => ({
455+
sendFetch: () => Promise.reject(new Error('500'))
456+
}));
431457

432458
const eventCache: EventCache =
433459
Utils.createDefaultEventCacheWithEvents();
@@ -444,11 +470,103 @@ describe('Dispatch tests', () => {
444470
dispatch.setAwsCredentials(Utils.createAwsCredentials());
445471

446472
// Run
447-
await expect(dispatch.dispatchFetch()).rejects.toEqual(ERROR);
448473
eventCache.recordEvent('com.amazon.rum.event1', {});
449474

450475
// Assert
451-
await expect(dispatch.dispatchFetch()).resolves.toEqual(undefined);
476+
await expect(dispatch.dispatchFetch()).rejects.toEqual(
477+
new Error('500')
478+
);
479+
expect((dispatch as unknown as any).enabled).toBe(true);
480+
});
481+
482+
test('when a fetch request is rejected with 401 then dispatch is disabled', async () => {
483+
// Init
484+
(DataPlaneClient as any).mockImplementationOnce(() => ({
485+
sendFetch: () => Promise.reject(new Error('401'))
486+
}));
487+
488+
const eventCache: EventCache =
489+
Utils.createDefaultEventCacheWithEvents();
490+
491+
const dispatch = new Dispatch(
492+
Utils.AWS_RUM_REGION,
493+
Utils.AWS_RUM_ENDPOINT,
494+
eventCache,
495+
{
496+
...DEFAULT_CONFIG,
497+
...{ dispatchInterval: Utils.AUTO_DISPATCH_OFF, retries: 0 }
498+
}
499+
);
500+
dispatch.setAwsCredentials(Utils.createAwsCredentials());
501+
502+
// Run
503+
eventCache.recordEvent('com.amazon.rum.event1', {});
504+
505+
// Assert
506+
await expect(dispatch.dispatchFetch()).rejects.toEqual(
507+
new Error('401')
508+
);
509+
expect((dispatch as unknown as any).enabled).toBe(false);
510+
});
511+
512+
test('when a fetch request is rejected with 403 then dispatch is disabled', async () => {
513+
// Init
514+
(DataPlaneClient as any).mockImplementationOnce(() => ({
515+
sendFetch: () => Promise.reject(new Error('403'))
516+
}));
517+
518+
const eventCache: EventCache =
519+
Utils.createDefaultEventCacheWithEvents();
520+
521+
const dispatch = new Dispatch(
522+
Utils.AWS_RUM_REGION,
523+
Utils.AWS_RUM_ENDPOINT,
524+
eventCache,
525+
{
526+
...DEFAULT_CONFIG,
527+
...{ dispatchInterval: Utils.AUTO_DISPATCH_OFF, retries: 0 }
528+
}
529+
);
530+
dispatch.setAwsCredentials(Utils.createAwsCredentials());
531+
532+
// Run
533+
eventCache.recordEvent('com.amazon.rum.event1', {});
534+
535+
// Assert
536+
await expect(dispatch.dispatchFetch()).rejects.toEqual(
537+
new Error('403')
538+
);
539+
expect((dispatch as unknown as any).enabled).toBe(false);
540+
});
541+
542+
test('when a fetch request is rejected with 404 then dispatch is disabled', async () => {
543+
// Init
544+
(DataPlaneClient as any).mockImplementationOnce(() => ({
545+
sendFetch: () => Promise.reject(new Error('404'))
546+
}));
547+
548+
const eventCache: EventCache =
549+
Utils.createDefaultEventCacheWithEvents();
550+
551+
const dispatch = new Dispatch(
552+
Utils.AWS_RUM_REGION,
553+
Utils.AWS_RUM_ENDPOINT,
554+
eventCache,
555+
{
556+
...DEFAULT_CONFIG,
557+
...{ dispatchInterval: Utils.AUTO_DISPATCH_OFF, retries: 0 }
558+
}
559+
);
560+
dispatch.setAwsCredentials(Utils.createAwsCredentials());
561+
562+
// Run
563+
eventCache.recordEvent('com.amazon.rum.event1', {});
564+
565+
// Assert
566+
await expect(dispatch.dispatchFetch()).rejects.toEqual(
567+
new Error('404')
568+
);
569+
expect((dispatch as unknown as any).enabled).toBe(false);
452570
});
453571

454572
test('when signing is disabled then credentials are not needed for dispatch', async () => {

0 commit comments

Comments
 (0)