1
1
/**
2
2
* @license
3
- * Copyright 2017 Google Inc.
3
+ * Copyright 2017 Google LLC
4
4
*
5
5
* Licensed under the Apache License, Version 2.0 (the "License");
6
6
* you may not use this file except in compliance with the License.
@@ -226,6 +226,14 @@ fireauth.storage.IndexedDB.VERSION_ = 1;
226
226
fireauth . storage . IndexedDB . POLLING_DELAY_ = 800 ;
227
227
228
228
229
+ /**
230
+ * Maximum number of times to retry a transaction in the event the connection is
231
+ * closed.
232
+ * @private @const {number}
233
+ */
234
+ fireauth . storage . IndexedDB . TRANSACTION_RETRY_COUNT_ = 3 ;
235
+
236
+
229
237
/**
230
238
* The indexedDB polling stop error.
231
239
* @private @const {string}
@@ -341,6 +349,37 @@ fireauth.storage.IndexedDB.prototype.initializeDbAndRun_ =
341
349
return this . initPromise_ ;
342
350
} ;
343
351
352
+ /**
353
+ * Attempts to run a transaction, in the event of an error will re-initialize
354
+ * the DB connection and retry a fixed number of times.
355
+ * @param {function(!IDBDatabase): !goog.Promise<{T}> } transaction A method
356
+ * which performs a transactional operation on an IDBDatabase.
357
+ * @template T
358
+ * @return {!goog.Promise<T> }
359
+ * @private
360
+ */
361
+ fireauth . storage . IndexedDB . prototype . withRetry_ = function ( transaction ) {
362
+ let numAttempts = 0 ;
363
+ const attempt = ( resolve , reject ) => {
364
+ this . initializeDbAndRun_ ( )
365
+ . then ( transaction )
366
+ . then ( resolve )
367
+ . thenCatch ( ( error ) => {
368
+ if ( ++ numAttempts >
369
+ fireauth . storage . IndexedDB . TRANSACTION_RETRY_COUNT_ ) {
370
+ reject ( error ) ;
371
+ return ;
372
+ }
373
+ return this . initializeDbAndRun_ ( ) . then ( ( db ) => {
374
+ db . close ( ) ;
375
+ this . initPromise_ = undefined ;
376
+ return attempt ( resolve , reject ) ;
377
+ } ) ;
378
+ } ) ;
379
+ } ;
380
+ return new goog . Promise ( attempt ) ;
381
+ }
382
+
344
383
345
384
/**
346
385
* @return {boolean } Whether indexedDB is available or not.
@@ -416,43 +455,42 @@ fireauth.storage.IndexedDB.prototype.onIDBRequest_ =
416
455
* @override
417
456
*/
418
457
fireauth . storage . IndexedDB . prototype . set = function ( key , value ) {
419
- var isLocked = false ;
420
- var dbTemp ;
421
- var self = this ;
422
- return this . initializeDbAndRun_ ( )
423
- . then ( function ( db ) {
424
- dbTemp = db ;
425
- var objectStore = self . getDataObjectStore_ (
426
- self . getTransaction_ ( dbTemp , true ) ) ;
427
- return self . onIDBRequest_ ( objectStore . get ( key ) ) ;
428
- } )
429
- . then ( function ( data ) {
430
- var objectStore = self . getDataObjectStore_ (
431
- self . getTransaction_ ( dbTemp , true ) ) ;
458
+ let isLocked = false ;
459
+ return this
460
+ . withRetry_ ( ( db ) => {
461
+ const objectStore =
462
+ this . getDataObjectStore_ ( this . getTransaction_ ( db , true ) ) ;
463
+ return this . onIDBRequest_ ( objectStore . get ( key ) ) ;
464
+ } )
465
+ . then ( ( data ) => {
466
+ return this . withRetry_ ( ( db ) => {
467
+ const objectStore =
468
+ this . getDataObjectStore_ ( this . getTransaction_ ( db , true ) ) ;
432
469
if ( data ) {
433
470
// Update the value(s) in the object that you want to change
434
471
data . value = value ;
435
472
// Put this updated object back into the database.
436
- return self . onIDBRequest_ ( objectStore . put ( data ) ) ;
473
+ return this . onIDBRequest_ ( objectStore . put ( data ) ) ;
437
474
}
438
- self . pendingOpsTracker_ ++ ;
475
+ this . pendingOpsTracker_ ++ ;
439
476
isLocked = true ;
440
- var obj = { } ;
441
- obj [ self . dataKeyPath_ ] = key ;
442
- obj [ self . valueKeyPath_ ] = value ;
443
- return self . onIDBRequest_ ( objectStore . add ( obj ) ) ;
444
- } )
445
- . then ( function ( ) {
446
- // Save in local copy to avoid triggering false external event.
447
- self . localMap_ [ key ] = value ;
448
- // Announce change in key to service worker.
449
- return self . notifySW_ ( key ) ;
450
- } )
451
- . thenAlways ( function ( ) {
452
- if ( isLocked ) {
453
- self . pendingOpsTracker_ -- ;
454
- }
477
+ const obj = { } ;
478
+ obj [ this . dataKeyPath_ ] = key ;
479
+ obj [ this . valueKeyPath_ ] = value ;
480
+ return this . onIDBRequest_ ( objectStore . add ( obj ) ) ;
455
481
} ) ;
482
+ } )
483
+ . then ( ( ) => {
484
+ // Save in local copy to avoid triggering false external event.
485
+ this . localMap_ [ key ] = value ;
486
+ // Announce change in key to service worker.
487
+ return this . notifySW_ ( key ) ;
488
+ } )
489
+ . thenAlways ( ( ) => {
490
+ if ( isLocked ) {
491
+ this . pendingOpsTracker_ -- ;
492
+ }
493
+ } ) ;
456
494
} ;
457
495
458
496
@@ -496,15 +534,14 @@ fireauth.storage.IndexedDB.prototype.notifySW_ = function(key) {
496
534
* @override
497
535
*/
498
536
fireauth . storage . IndexedDB . prototype . get = function ( key ) {
499
- var self = this ;
500
- return this . initializeDbAndRun_ ( )
501
- . then ( function ( db ) {
502
- return self . onIDBRequest_ (
503
- self . getDataObjectStore_ ( self . getTransaction_ ( db , false ) ) . get ( key ) ) ;
504
- } )
505
- . then ( function ( response ) {
506
- return response && response . value ;
507
- } ) ;
537
+ return this
538
+ . withRetry_ ( ( db ) => {
539
+ return this . onIDBRequest_ (
540
+ this . getDataObjectStore_ ( this . getTransaction_ ( db , false ) ) . get ( key ) ) ;
541
+ } )
542
+ . then ( ( response ) => {
543
+ return response && response . value ;
544
+ } ) ;
508
545
} ;
509
546
510
547
@@ -516,23 +553,22 @@ fireauth.storage.IndexedDB.prototype.get = function(key) {
516
553
* @override
517
554
*/
518
555
fireauth . storage . IndexedDB . prototype . remove = function ( key ) {
519
- var isLocked = false ;
520
- var self = this ;
521
- return this . initializeDbAndRun_ ( )
522
- . then ( function ( db ) {
556
+ let isLocked = false ;
557
+ return this
558
+ . withRetry_ ( ( db ) => {
523
559
isLocked = true ;
524
- self . pendingOpsTracker_ ++ ;
525
- return self . onIDBRequest_ (
526
- self . getDataObjectStore_ (
527
- self . getTransaction_ ( db , true ) ) [ 'delete' ] ( key ) ) ;
528
- } ) . then ( function ( ) {
560
+ this . pendingOpsTracker_ ++ ;
561
+ return this . onIDBRequest_ (
562
+ this . getDataObjectStore_ (
563
+ this . getTransaction_ ( db , true ) ) [ 'delete' ] ( key ) ) ;
564
+ } ) . then ( ( ) => {
529
565
// Delete from local copy to avoid triggering false external event.
530
- delete self . localMap_ [ key ] ;
566
+ delete this . localMap_ [ key ] ;
531
567
// Announce change in key to service worker.
532
- return self . notifySW_ ( key ) ;
533
- } ) . thenAlways ( function ( ) {
568
+ return this . notifySW_ ( key ) ;
569
+ } ) . thenAlways ( ( ) => {
534
570
if ( isLocked ) {
535
- self . pendingOpsTracker_ -- ;
571
+ this . pendingOpsTracker_ -- ;
536
572
}
537
573
} ) ;
538
574
} ;
0 commit comments