@@ -45,6 +45,7 @@ import { SDK_VERSION } from './version';
45
45
46
46
const RECONNECT_MIN_DELAY = 1000 ;
47
47
const RECONNECT_MAX_DELAY_DEFAULT = 60 * 5 * 1000 ; // 5 minutes in milliseconds (Case: 1858)
48
+ const GET_CONNECT_TIMEOUT = 3 * 1000 ;
48
49
const RECONNECT_MAX_DELAY_FOR_ADMINS = 30 * 1000 ; // 30 seconds for admin clients (likely to be a backend server)
49
50
const RECONNECT_DELAY_MULTIPLIER = 1.3 ;
50
51
const RECONNECT_DELAY_RESET_TIMEOUT = 30000 ; // Reset delay back to MIN_DELAY after being connected for 30sec.
@@ -76,6 +77,12 @@ interface OutstandingPut {
76
77
onComplete : ( a : string , b ?: string ) => void ;
77
78
}
78
79
80
+ interface OutstandingGet {
81
+ action : string ;
82
+ request : object ;
83
+ onComplete : ( response : { [ k : string ] : unknown } ) => void ;
84
+ }
85
+
79
86
/**
80
87
* Firebase connection. Abstracts wire protocol and handles reconnecting.
81
88
*
@@ -94,7 +101,9 @@ export class PersistentConnection extends ServerActions {
94
101
Map < /* queryId */ string , ListenSpec >
95
102
> = new Map ( ) ;
96
103
private outstandingPuts_ : OutstandingPut [ ] = [ ] ;
104
+ private outstandingGets_ : OutstandingGet [ ] = [ ] ;
97
105
private outstandingPutCount_ = 0 ;
106
+ private outstandingGetCount_ = 0 ;
98
107
private onDisconnectRequestQueue_ : OnDisconnectRequest [ ] = [ ] ;
99
108
private connected_ = false ;
100
109
private reconnectDelay_ = RECONNECT_MIN_DELAY ;
@@ -186,15 +195,55 @@ export class PersistentConnection extends ServerActions {
186
195
}
187
196
188
197
get ( query : Query ) : Promise < string > {
189
- const req : { [ k : string ] : unknown } = {
198
+ const deferred = new Deferred < string > ( ) ;
199
+ const request = {
190
200
p : query . path . toString ( ) ,
191
201
q : query . queryObject ( )
192
202
} ;
203
+ const outstandingGet = {
204
+ action : 'g' ,
205
+ request,
206
+ onComplete : ( message : { [ k : string ] : unknown } ) => {
207
+ const payload = message [ 'd' ] as string ;
208
+ if ( message [ 's' ] === 'ok' ) {
209
+ this . onDataUpdate_ (
210
+ request [ 'p' ] ,
211
+ payload ,
212
+ /*isMerge*/ false ,
213
+ /*tag*/ null
214
+ ) ;
215
+ deferred . resolve ( payload ) ;
216
+ } else {
217
+ deferred . reject ( payload ) ;
218
+ }
219
+ }
220
+ } ;
221
+ this . outstandingGets_ . push ( outstandingGet ) ;
222
+ this . outstandingGetCount_ ++ ;
223
+ const index = this . outstandingGets_ . length - 1 ;
224
+
225
+ if ( ! this . connected_ ) {
226
+ const self = this ;
227
+ setTimeout ( function ( ) {
228
+ const get = self . outstandingGets_ [ index ] ;
229
+ if ( get === undefined || outstandingGet !== get ) {
230
+ return ;
231
+ }
232
+ delete self . outstandingGets_ [ index ] ;
233
+ self . outstandingGetCount_ -- ;
234
+ if ( self . outstandingGetCount_ === 0 ) {
235
+ self . outstandingGets_ = [ ] ;
236
+ }
237
+ self . log_ ( 'get ' + index + ' timed out on connection' ) ;
238
+ deferred . reject ( new Error ( 'Client is offline.' ) ) ;
239
+ } , GET_CONNECT_TIMEOUT ) ;
240
+ }
241
+
193
242
if ( this . connected_ ) {
194
- return this . sendGet_ ( req ) ;
195
- } else {
196
- return Promise . reject ( new Error ( 'Client is offline' ) ) ;
243
+ this . sendGet_ ( index ) ;
197
244
}
245
+
246
+ return deferred . promise ;
198
247
}
199
248
200
249
/**
@@ -214,7 +263,7 @@ export class PersistentConnection extends ServerActions {
214
263
}
215
264
assert (
216
265
query . getQueryParams ( ) . isDefault ( ) ||
217
- ! query . getQueryParams ( ) . loadsAllData ( ) ,
266
+ ! query . getQueryParams ( ) . loadsAllData ( ) ,
218
267
'listen() called for non-default but complete query'
219
268
) ;
220
269
assert (
@@ -234,23 +283,22 @@ export class PersistentConnection extends ServerActions {
234
283
}
235
284
}
236
285
237
- private sendGet_ ( request : object ) : Promise < string > {
238
- return new Promise ( ( resolve , reject ) => {
239
- this . sendRequest ( 'g' , request , ( message : { [ k : string ] : unknown } ) => {
240
- const payload = message [ 'd' ] as string ;
241
- if ( message [ 's' ] === 'ok' ) {
242
- this . onDataUpdate_ (
243
- request [ 'p' ] ,
244
- payload ,
245
- /*isMerge*/ false ,
246
- /*tag*/ null
247
- ) ;
248
- resolve ( payload ) ;
249
- } else {
250
- reject ( payload ) ;
286
+ private sendGet_ ( index : number ) {
287
+ const get = this . outstandingGets_ [ index ] ;
288
+ this . sendRequest (
289
+ get . action ,
290
+ get . request ,
291
+ ( message : { [ k : string ] : unknown } ) => {
292
+ delete this . outstandingGets_ [ index ] ;
293
+ this . outstandingGetCount_ -- ;
294
+ if ( this . outstandingGetCount_ === 0 ) {
295
+ this . outstandingGets_ = [ ] ;
251
296
}
252
- } ) ;
253
- } ) ;
297
+ if ( get . onComplete ) {
298
+ get . onComplete ( message ) ;
299
+ }
300
+ }
301
+ ) ;
254
302
}
255
303
256
304
private sendListen_ ( listenSpec : ListenSpec ) {
@@ -305,8 +353,8 @@ export class PersistentConnection extends ServerActions {
305
353
const indexPath = query . path . toString ( ) ;
306
354
warn (
307
355
`Using an unspecified index. Your data will be downloaded and ` +
308
- `filtered on the client. Consider adding ${ indexSpec } at ` +
309
- `${ indexPath } to your security rules for better performance.`
356
+ `filtered on the client. Consider adding ${ indexSpec } at ` +
357
+ `${ indexPath } to your security rules for better performance.`
310
358
) ;
311
359
}
312
360
}
@@ -324,7 +372,7 @@ export class PersistentConnection extends ServerActions {
324
372
//If we're connected we want to let the server know to unauthenticate us. If we're not connected, simply delete
325
373
//the credential so we dont become authenticated next time we connect.
326
374
if ( this . connected_ ) {
327
- this . sendRequest ( 'unauth' , { } , ( ) => { } ) ;
375
+ this . sendRequest ( 'unauth' , { } , ( ) => { } ) ;
328
376
}
329
377
}
330
378
@@ -388,7 +436,7 @@ export class PersistentConnection extends ServerActions {
388
436
389
437
assert (
390
438
query . getQueryParams ( ) . isDefault ( ) ||
391
- ! query . getQueryParams ( ) . loadsAllData ( ) ,
439
+ ! query . getQueryParams ( ) . loadsAllData ( ) ,
392
440
'unlisten() called for non-default but complete query'
393
441
) ;
394
442
const listen = this . removeListen_ ( pathString , queryId ) ;
@@ -646,8 +694,8 @@ export class PersistentConnection extends ServerActions {
646
694
} else {
647
695
error (
648
696
'Unrecognized action received from server: ' +
649
- stringify ( action ) +
650
- '\nAre you using the latest client?'
697
+ stringify ( action ) +
698
+ '\nAre you using the latest client?'
651
699
) ;
652
700
}
653
701
}
@@ -982,6 +1030,12 @@ export class PersistentConnection extends ServerActions {
982
1030
request . onComplete
983
1031
) ;
984
1032
}
1033
+
1034
+ for ( let i = 0 ; i < this . outstandingGets_ . length ; i ++ ) {
1035
+ if ( this . outstandingGets_ [ i ] ) {
1036
+ this . sendGet_ ( i ) ;
1037
+ }
1038
+ }
985
1039
}
986
1040
987
1041
/**
0 commit comments