File tree Expand file tree Collapse file tree 5 files changed +59
-4
lines changed
__tests__/internal/events Expand file tree Collapse file tree 5 files changed +59
-4
lines changed Original file line number Diff line number Diff line change @@ -658,7 +658,9 @@ describe('given an event processor', () => {
658658 await expect ( eventProcessor . flush ( ) ) . rejects . toThrow ( 'some error' ) ;
659659
660660 eventProcessor . sendEvent ( new InputIdentifyEvent ( Context . fromLDContext ( user ) ) ) ;
661- await expect ( eventProcessor . flush ( ) ) . rejects . toThrow ( / S D K k e y i s i n v a l i d / ) ;
661+ await expect ( eventProcessor . flush ( ) ) . rejects . toThrow (
662+ 'Events cannot be posted because a permanent error has been encountered.' ,
663+ ) ;
662664 } ) ;
663665
664666 it ( 'swallows errors from failed background flush' , async ( ) => {
Original file line number Diff line number Diff line change @@ -43,9 +43,29 @@ export class LDClientError extends Error {
4343 }
4444}
4545
46+ /**
47+ * Check if the HTTP error is recoverable. This will return false if a request
48+ * made with any payload could not recover. If the reason for the failure
49+ * is payload specific, for instance a payload that is too large, then
50+ * it could recover with a different payload.
51+ */
4652export function isHttpRecoverable ( status : number ) {
4753 if ( status >= 400 && status < 500 ) {
4854 return status === 400 || status === 408 || status === 429 ;
4955 }
5056 return true ;
5157}
58+
59+ /**
60+ * Returns true if the status could recover for a different payload.
61+ *
62+ * When used with event processing this indicates that we should discard
63+ * the payload, but that a subsequent payload may succeed. Therefore we should
64+ * not stop event processing.
65+ */
66+ export function isHttpLocallyRecoverable ( status : number ) {
67+ if ( status === 413 ) {
68+ return true ;
69+ }
70+ return isHttpRecoverable ( status ) ;
71+ }
Original file line number Diff line number Diff line change @@ -168,7 +168,11 @@ export default class EventProcessor implements LDEventProcessor {
168168
169169 async flush ( ) : Promise < void > {
170170 if ( this . shutdown ) {
171- throw new LDInvalidSDKKeyError ( 'Events cannot be posted because SDK key is invalid' ) ;
171+ throw new LDInvalidSDKKeyError (
172+ 'Events cannot be posted because a permanent error has been encountered. ' +
173+ 'This is most likely an invalid SDK key. The specific error information ' +
174+ 'is logged independently.' ,
175+ ) ;
172176 }
173177
174178 const eventsToFlush = this . queue ;
Original file line number Diff line number Diff line change @@ -196,6 +196,23 @@ describe('given an event sender', () => {
196196 } ) ;
197197 } ) ;
198198
199+ it ( 'given a result for too large of a payload' , async ( ) => {
200+ setupMockFetch ( 413 ) ;
201+ eventSenderResult = await eventSender . sendEventData (
202+ LDEventType . AnalyticsEvents ,
203+ testEventData1 ,
204+ ) ;
205+
206+ const errorMessage = `Received error 413 for event posting - giving up permanently` ;
207+
208+ const { status, error } = eventSenderResult ;
209+
210+ expect ( mockFetch ) . toHaveBeenCalledTimes ( 1 ) ;
211+ expect ( status ) . toEqual ( LDDeliveryStatus . Failed ) ;
212+ expect ( error . name ) . toEqual ( 'LaunchDarklyUnexpectedResponseError' ) ;
213+ expect ( error . message ) . toEqual ( errorMessage ) ;
214+ } ) ;
215+
199216 describe . each ( [ 401 , 403 ] ) ( 'given unrecoverable errors' , ( responseStatusCode ) => {
200217 beforeEach ( async ( ) => {
201218 setupMockFetch ( responseStatusCode ) ;
Original file line number Diff line number Diff line change @@ -5,7 +5,11 @@ import {
55 LDEventSenderResult ,
66 LDEventType ,
77} from '../../api/subsystem' ;
8- import { isHttpRecoverable , LDUnexpectedResponseError } from '../../errors' ;
8+ import {
9+ isHttpLocallyRecoverable ,
10+ isHttpRecoverable ,
11+ LDUnexpectedResponseError ,
12+ } from '../../errors' ;
913import { ClientContext } from '../../options' ;
1014import { defaultHeaders , httpErrorMessage , sleep } from '../../utils' ;
1115
@@ -80,7 +84,15 @@ export default class EventSender implements LDEventSender {
8084 ) ;
8185
8286 if ( ! isHttpRecoverable ( status ) ) {
83- tryRes . status = LDDeliveryStatus . FailedAndMustShutDown ;
87+ // If the HTTP request isn't recoverable. Meaning if we made the same request it
88+ // would not recover, then we check if a different request could recover.
89+ // If a different request could not recover, then we shutdown. If a different request could
90+ // recover, then we just don't retry this specific request.
91+ if ( ! isHttpLocallyRecoverable ( status ) ) {
92+ tryRes . status = LDDeliveryStatus . FailedAndMustShutDown ;
93+ } else {
94+ tryRes . status = LDDeliveryStatus . Failed ;
95+ }
8496 tryRes . error = error ;
8597 return tryRes ;
8698 }
You can’t perform that action at this time.
0 commit comments