1515 * limitations under the License.
1616 */
1717
18- import { _FirebaseInstallationsInternal } from " @firebase/installations" ;
19- import { ConfigUpdateObserver } from " ../public_types" ;
20- import { calculateBackoffMillis , FirebaseError } from " @firebase/util" ;
21- import { ERROR_FACTORY , ErrorCode } from " ../errors" ;
22- import { Storage } from " ../storage/storage" ;
18+ import { _FirebaseInstallationsInternal } from ' @firebase/installations' ;
19+ import { ConfigUpdateObserver } from ' ../public_types' ;
20+ import { calculateBackoffMillis , FirebaseError } from ' @firebase/util' ;
21+ import { ERROR_FACTORY , ErrorCode } from ' ../errors' ;
22+ import { Storage } from ' ../storage/storage' ;
2323import { isBefore } from 'date-fns' ;
2424
2525const API_KEY_HEADER = 'X-Goog-Api-Key' ;
@@ -36,66 +36,66 @@ export class RealtimeHandler {
3636 private readonly namespace : string ,
3737 private readonly projectId : string ,
3838 private readonly apiKey : string ,
39- private readonly appId : string ,
40- ) {
41- this . httpRetriesRemaining = ORIGINAL_RETRIES ;
39+ private readonly appId : string
40+ ) {
4241 this . setRetriesRemaining ( ) ;
4342 }
4443
45- private observers : Set < ConfigUpdateObserver > = new Set < ConfigUpdateObserver > ( ) ;
44+ private observers : Set < ConfigUpdateObserver > =
45+ new Set < ConfigUpdateObserver > ( ) ;
4646 private isConnectionActive : boolean = false ;
4747 private isRealtimeDisabled : boolean = false ;
4848 private controller ?: AbortController ;
4949 private reader : ReadableStreamDefaultReader | undefined ;
5050 private httpRetriesRemaining : number = ORIGINAL_RETRIES ;
5151
5252 private async setRetriesRemaining ( ) {
53- // Retrieve number of remaining retries from last session. The minimum retry count being one.
54- const metadata = await this . storage . getRealtimeBackoffMetadata ( ) ;
55- const numFailedStreams = metadata ?. numFailedStreams || 0 ;
56- this . httpRetriesRemaining = Math . max ( ORIGINAL_RETRIES - numFailedStreams , 1 ) ;
57- }
58-
59- /**
60- * Removes an observer from the realtime updates.
61- * @param observer The observer to remove.
62- */
63- removeObserver ( observer : ConfigUpdateObserver ) : void {
64- if ( this . observers . has ( observer ) ) {
65- this . observers . delete ( observer ) ;
66- }
53+ // Retrieve number of remaining retries from last session. The minimum retry count being one.
54+ const metadata = await this . storage . getRealtimeBackoffMetadata ( ) ;
55+ const numFailedStreams = metadata ?. numFailedStreams || 0 ;
56+ this . httpRetriesRemaining = Math . max (
57+ ORIGINAL_RETRIES - numFailedStreams ,
58+ 1
59+ ) ;
6760 }
6861
69- private propagateError = ( e : FirebaseError ) => this . observers . forEach ( o => o . error ?.( e ) ) ;
62+ private propagateError = ( e : FirebaseError ) =>
63+ this . observers . forEach ( o => o . error ?.( e ) ) ;
7064
7165 /**
7266 * Increment the number of failed stream attempts, increase the backoff duration, set the backoff
7367 * end time to "backoff duration" after {@code lastFailedStreamTime} and persist the new
7468 * values to storage metadata.
7569 */
76- private async updateBackoffMetadataWithLastFailedStreamConnectionTime ( lastFailedStreamTime : Date ) : Promise < void > {
77- const numFailedStreams = ( ( await this . storage . getRealtimeBackoffMetadata ( ) ) ?. numFailedStreams || 0 ) + 1 ;
70+ private async updateBackoffMetadataWithLastFailedStreamConnectionTime (
71+ lastFailedStreamTime : Date
72+ ) : Promise < void > {
73+ const numFailedStreams =
74+ ( ( await this . storage . getRealtimeBackoffMetadata ( ) ) ?. numFailedStreams ||
75+ 0 ) + 1 ;
7876 const backoffMillis = calculateBackoffMillis ( numFailedStreams ) ;
7977 await this . storage . setRealtimeBackoffMetadata ( {
80- backoffEndTimeMillis : new Date ( lastFailedStreamTime . getTime ( ) + backoffMillis ) ,
78+ backoffEndTimeMillis : new Date (
79+ lastFailedStreamTime . getTime ( ) + backoffMillis
80+ ) ,
8181 numFailedStreams
8282 } ) ;
8383 }
84-
84+
8585 /**
8686 * HTTP status code that the Realtime client should retry on.
8787 */
8888 private isStatusCodeRetryable = ( statusCode ?: number ) : boolean => {
8989 const retryableStatusCodes = [
90- 408 , // Request Timeout
91- 429 , // Too Many Requests
92- 502 , // Bad Gateway
93- 503 , // Service Unavailable
94- 504 // Gateway Timeout
90+ 408 , // Request Timeout
91+ 429 , // Too Many Requests
92+ 502 , // Bad Gateway
93+ 503 , // Service Unavailable
94+ 504 // Gateway Timeout
9595 ] ;
9696 return ! statusCode || retryableStatusCodes . includes ( statusCode ) ;
97- }
98-
97+ } ;
98+
9999 /**
100100 * Stops the real-time HTTP connection by aborting the in-progress fetch request
101101 * and canceling the stream reader if they exist.
@@ -111,34 +111,40 @@ export class RealtimeHandler {
111111 this . reader = undefined ;
112112 }
113113 }
114-
114+
115115 private async resetRealtimeBackoff ( ) : Promise < void > {
116116 await this . storage . setRealtimeBackoffMetadata ( {
117117 backoffEndTimeMillis : new Date ( - 1 ) ,
118118 numFailedStreams : 0
119119 } ) ;
120- }
121-
120+ }
121+
122122 private resetRetryCount ( ) : void {
123123 this . httpRetriesRemaining = ORIGINAL_RETRIES ;
124124 }
125-
125+
126126 /**
127127 * Assembles the request headers and body and executes the fetch request to
128128 * establish the real-time streaming connection. This is the "worker" method
129129 * that performs the actual network communication.
130- */
131- private async establishRealtimeConnection ( url : URL , installationId : string , installationTokenResult : string , signal : AbortSignal ) : Promise < Response > {
130+ */
131+ private async establishRealtimeConnection (
132+ url : URL ,
133+ installationId : string ,
134+ installationTokenResult : string ,
135+ signal : AbortSignal
136+ ) : Promise < Response > {
132137 const eTagValue = await this . storage . getActiveConfigEtag ( ) ;
133- const lastKnownVersionNumber = await this . storage . getLastKnownTemplateVersion ( ) ;
134-
138+ const lastKnownVersionNumber =
139+ await this . storage . getLastKnownTemplateVersion ( ) ;
140+
135141 const headers = {
136142 [ API_KEY_HEADER ] : this . apiKey ,
137143 [ INSTALLATIONS_AUTH_TOKEN_HEADER ] : installationTokenResult ,
138144 'Content-Type' : 'application/json' ,
139145 'Accept' : 'application/json' ,
140146 'If-None-Match' : eTagValue || '*' ,
141- 'Content-Encoding' : 'gzip' ,
147+ 'Content-Encoding' : 'gzip'
142148 } ;
143149
144150 const requestBody = {
@@ -175,7 +181,12 @@ export class RealtimeHandler {
175181 ] ) ;
176182 this . controller = new AbortController ( ) ;
177183 const url = this . getRealtimeUrl ( ) ;
178- return await this . establishRealtimeConnection ( url , installationId , installationTokenResult , this . controller . signal ) ;
184+ return await this . establishRealtimeConnection (
185+ url ,
186+ installationId ,
187+ installationTokenResult ,
188+ this . controller . signal
189+ ) ;
179190 }
180191
181192 /**
@@ -187,9 +198,11 @@ export class RealtimeHandler {
187198 backoffMetadata = {
188199 backoffEndTimeMillis : new Date ( NO_BACKOFF_TIME_IN_MILLIS ) ,
189200 numFailedStreams : NO_FAILED_REALTIME_STREAMS
190- }
191- }
192- const backoffEndTime = new Date ( backoffMetadata . backoffEndTimeMillis ) . getTime ( ) ;
201+ } ;
202+ }
203+ const backoffEndTime = new Date (
204+ backoffMetadata . backoffEndTimeMillis
205+ ) . getTime ( ) ;
193206 const currentTime = Date . now ( ) ;
194207 const retryMillis = Math . max ( 0 , backoffEndTime - currentTime ) ;
195208 this . makeRealtimeHttpConnection ( retryMillis ) ;
@@ -218,12 +231,13 @@ export class RealtimeHandler {
218231 if ( ! this . checkAndSetHttpConnectionFlagIfNotRunning ( ) ) {
219232 return ;
220233 }
234+
221235 let backoffMetadata = await this . storage . getRealtimeBackoffMetadata ( ) ;
222236 if ( ! backoffMetadata ) {
223237 backoffMetadata = {
224238 backoffEndTimeMillis : new Date ( NO_BACKOFF_TIME_IN_MILLIS ) ,
225239 numFailedStreams : NO_FAILED_REALTIME_STREAMS
226- }
240+ } ;
227241 }
228242 const backoffEndTime = backoffMetadata . backoffEndTimeMillis . getTime ( ) ;
229243 if ( isBefore ( new Date ( ) , backoffEndTime ) ) {
@@ -234,47 +248,56 @@ export class RealtimeHandler {
234248 let response : Response | undefined ;
235249 let responseCode : number | undefined ;
236250 try {
237- //this has been called in the try cause it throws an error if the method does not get implemented
238- response = await this . createRealtimeConnection ( ) ;
239- responseCode = response . status ;
240- if ( response . ok && response . body ) {
241- this . resetRetryCount ( ) ;
242- await this . resetRealtimeBackoff ( ) ;
243- //const configAutoFetch = this.startAutoFetch(reader);
244- //await configAutoFetch.listenForNotifications();
245- }
251+ //this has been called in the try cause it throws an error if the method does not get implemented
252+ response = await this . createRealtimeConnection ( ) ;
253+ responseCode = response . status ;
254+ if ( response . ok && response . body ) {
255+ this . resetRetryCount ( ) ;
256+ await this . resetRealtimeBackoff ( ) ;
257+ //const configAutoFetch = this.startAutoFetch(reader);
258+ //await configAutoFetch.listenForNotifications();
259+ }
246260 } catch ( error ) {
247261 //there might have been a transient error so the client will retry the connection.
248- console . error ( 'Exception connecting to real-time RC backend. Retrying the connection...:' , error ) ;
262+ console . error (
263+ 'Exception connecting to real-time RC backend. Retrying the connection...:' ,
264+ error
265+ ) ;
249266 } finally {
250267 // Close HTTP connection and associated streams.
251268 this . closeRealtimeHttpConnection ( ) ;
252269 this . setIsHttpConnectionRunning ( false ) ;
253-
270+
254271 // Update backoff metadata if the connection failed in the foreground.
255- const connectionFailed = responseCode == null || this . isStatusCodeRetryable ( responseCode ) ;
272+ const connectionFailed =
273+ responseCode == null || this . isStatusCodeRetryable ( responseCode ) ;
256274
257275 if ( connectionFailed ) {
258- await this . updateBackoffMetadataWithLastFailedStreamConnectionTime ( new Date ( ) ) ;
276+ await this . updateBackoffMetadataWithLastFailedStreamConnectionTime (
277+ new Date ( )
278+ ) ;
259279 }
260280 // If responseCode is null then no connection was made to server and the SDK should still retry.
261- if ( connectionFailed || response ?. ok ) {
281+ if ( connectionFailed || response ?. ok ) {
262282 await this . retryHttpConnectionWhenBackoffEnds ( ) ;
263283 } else {
264284 let errorMessage = `Unable to connect to the server. HTTP status code: ${ responseCode } ` ;
265- const firebaseError = ERROR_FACTORY . create ( ErrorCode . CONFIG_UPDATE_STREAM_ERROR , {
266- httpStatus : responseCode ,
267- originalErrorMessage : errorMessage
268- } ) ;
285+ const firebaseError = ERROR_FACTORY . create (
286+ ErrorCode . CONFIG_UPDATE_STREAM_ERROR ,
287+ {
288+ httpStatus : responseCode ,
289+ originalErrorMessage : errorMessage
290+ }
291+ ) ;
269292 this . propagateError ( firebaseError ) ;
270293 }
271294 }
272295 }
273296
274297 /**
275- * Checks whether connection can be made or not based on some conditions
276- * @returns booelean
277- */
298+ * Checks whether connection can be made or not based on some conditions
299+ * @returns booelean
300+ */
278301 private canEstablishStreamConnection ( ) : boolean {
279302 const hasActiveListeners = this . observers . size > 0 ;
280303 const isNotDisabled = ! this . isRealtimeDisabled ;
@@ -301,11 +324,21 @@ export class RealtimeHandler {
301324 }
302325
303326 /**
304- * Adds an observer to the realtime updates.
305- * @param observer The observer to add.
306- */
327+ * Adds an observer to the realtime updates.
328+ * @param observer The observer to add.
329+ */
307330 async addObserver ( observer : ConfigUpdateObserver ) : Promise < void > {
308331 this . observers . add ( observer ) ;
309332 await this . beginRealtime ( ) ;
310333 }
334+
335+ /**
336+ * Removes an observer from the realtime updates.
337+ * @param observer The observer to remove.
338+ */
339+ removeObserver ( observer : ConfigUpdateObserver ) : void {
340+ if ( this . observers . has ( observer ) ) {
341+ this . observers . delete ( observer ) ;
342+ }
343+ }
311344}
0 commit comments