@@ -6,12 +6,15 @@ import {
66 DataSourcePaths ,
77 DataSourceState ,
88 FlagManager ,
9+ httpErrorMessage ,
910 internal ,
1011 LDEmitter ,
1112 LDHeaders ,
1213 LDIdentifyOptions ,
1314 makeRequestor ,
1415 Platform ,
16+ shouldRetry ,
17+ sleep ,
1518} from '@launchdarkly/js-client-sdk-common' ;
1619
1720import { readFlagsFromBootstrap } from './bootstrap' ;
@@ -97,34 +100,84 @@ export default class BrowserDataManager extends BaseDataManager {
97100 this . _debugLog ( 'Identify - Flags loaded from cache. Continuing to initialize via a poll.' ) ;
98101 }
99102
100- await this . _finishIdentifyFromPoll ( context , identifyResolve , identifyReject ) ;
103+ await this . _finishIdentifyFromPoll (
104+ context ,
105+ identifyResolve ,
106+ identifyReject ,
107+ browserIdentifyOptions ?. initialPollingRetries ,
108+ ) ;
101109 }
102110 this . _updateStreamingState ( ) ;
103111 }
104112
113+ /**
114+ * A helper function for the initial poll request. This is mainly here to facilitate
115+ * the retry logic.
116+ *
117+ * @param context - LDContext to request payload for.
118+ * @param maxRetries - Maximum number of retries to attempt. Defaults to 3.
119+ * @returns Payload as a string.
120+ */
121+ private async _requestPayload ( context : Context , maxRetries : number = 3 ) : Promise < string > {
122+ const plainContextString = JSON . stringify ( Context . toLDContext ( context ) ) ;
123+ const pollingRequestor = makeRequestor (
124+ plainContextString ,
125+ this . config . serviceEndpoints ,
126+ this . getPollingPaths ( ) ,
127+ this . platform . requests ,
128+ this . platform . encoding ! ,
129+ this . baseHeaders ,
130+ [ ] ,
131+ this . config . withReasons ,
132+ this . config . useReport ,
133+ this . _secureModeHash ,
134+ ) ;
135+
136+ let lastError : any ;
137+ let validMaxRetries = maxRetries ?? 3 ;
138+
139+ if ( validMaxRetries < 1 ) {
140+ this . logger . warn (
141+ `initialPollingRetries is set to ${ maxRetries } , which is less than 1. This is not supported and will be ignored. Defaulting to 3 retries.` ,
142+ ) ;
143+ validMaxRetries = 3 ;
144+ }
145+
146+ for ( let attempt = 0 ; attempt <= validMaxRetries ; attempt += 1 ) {
147+ try {
148+ // eslint-disable-next-line no-await-in-loop
149+ return await pollingRequestor . requestPayload ( ) ;
150+ } catch ( e : any ) {
151+ if ( ! shouldRetry ( e ) ) {
152+ throw e ;
153+ }
154+ lastError = e ;
155+ this . _debugLog ( httpErrorMessage ( e , 'initial poll request' , 'will retry' ) ) ;
156+ // NOTE: current we are hardcoding the retry interval to 1 second.
157+ // We can make this configurable in the future.
158+ // TODO: Reviewer any thoughts on this? Probably the easiest thing is to make this configurable
159+ // however, we can also look into using the backoff logic to calculate the delay?
160+ if ( attempt < validMaxRetries ) {
161+ // eslint-disable-next-line no-await-in-loop
162+ await sleep ( 1000 ) ;
163+ }
164+ }
165+ }
166+
167+ throw lastError ;
168+ }
169+
105170 private async _finishIdentifyFromPoll (
106171 context : Context ,
107172 identifyResolve : ( ) => void ,
108173 identifyReject : ( err : Error ) => void ,
174+ initialPollingRetries : number = 3 ,
109175 ) {
110176 try {
111177 this . dataSourceStatusManager . requestStateUpdate ( DataSourceState . Initializing ) ;
112178
113- const plainContextString = JSON . stringify ( Context . toLDContext ( context ) ) ;
114- const pollingRequestor = makeRequestor (
115- plainContextString ,
116- this . config . serviceEndpoints ,
117- this . getPollingPaths ( ) ,
118- this . platform . requests ,
119- this . platform . encoding ! ,
120- this . baseHeaders ,
121- [ ] ,
122- this . config . withReasons ,
123- this . config . useReport ,
124- this . _secureModeHash ,
125- ) ;
179+ const payload = await this . _requestPayload ( context , initialPollingRetries ) ;
126180
127- const payload = await pollingRequestor . requestPayload ( ) ;
128181 try {
129182 const listeners = this . createStreamListeners ( context , identifyResolve ) ;
130183 const putListener = listeners . get ( 'put' ) ;
0 commit comments