@@ -26,7 +26,8 @@ import {
26
26
isValidFormat ,
27
27
isMobileCordova ,
28
28
isReactNative ,
29
- isNodeSdk
29
+ isNodeSdk ,
30
+ Deferred
30
31
} from '@firebase/util' ;
31
32
32
33
import { error , log , logWrapper , warn , ObjectToUniqueKey } from './util/util' ;
@@ -44,6 +45,7 @@ import { SDK_VERSION } from './version';
44
45
45
46
const RECONNECT_MIN_DELAY = 1000 ;
46
47
const RECONNECT_MAX_DELAY_DEFAULT = 60 * 5 * 1000 ; // 5 minutes in milliseconds (Case: 1858)
48
+ const GET_CONNECT_TIMEOUT = 3 * 1000 ;
47
49
const RECONNECT_MAX_DELAY_FOR_ADMINS = 30 * 1000 ; // 30 seconds for admin clients (likely to be a backend server)
48
50
const RECONNECT_DELAY_MULTIPLIER = 1.3 ;
49
51
const RECONNECT_DELAY_RESET_TIMEOUT = 30000 ; // Reset delay back to MIN_DELAY after being connected for 30sec.
@@ -75,6 +77,12 @@ interface OutstandingPut {
75
77
onComplete : ( a : string , b ?: string ) => void ;
76
78
}
77
79
80
+ interface OutstandingGet {
81
+ action : string ;
82
+ request : object ;
83
+ onComplete : ( response : { [ k : string ] : unknown } ) => void ;
84
+ }
85
+
78
86
/**
79
87
* Firebase connection. Abstracts wire protocol and handles reconnecting.
80
88
*
@@ -93,7 +101,9 @@ export class PersistentConnection extends ServerActions {
93
101
Map < /* queryId */ string , ListenSpec >
94
102
> = new Map ( ) ;
95
103
private outstandingPuts_ : OutstandingPut [ ] = [ ] ;
104
+ private outstandingGets_ : OutstandingGet [ ] = [ ] ;
96
105
private outstandingPutCount_ = 0 ;
106
+ private outstandingGetCount_ = 0 ;
97
107
private onDisconnectRequestQueue_ : OnDisconnectRequest [ ] = [ ] ;
98
108
private connected_ = false ;
99
109
private reconnectDelay_ = RECONNECT_MIN_DELAY ;
@@ -184,6 +194,58 @@ export class PersistentConnection extends ServerActions {
184
194
}
185
195
}
186
196
197
+ get ( query : Query ) : Promise < string > {
198
+ const deferred = new Deferred < string > ( ) ;
199
+ const request = {
200
+ p : query . path . toString ( ) ,
201
+ q : query . queryObject ( )
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 ( ( ) => {
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
+
242
+ if ( this . connected_ ) {
243
+ this . sendGet_ ( index ) ;
244
+ }
245
+
246
+ return deferred . promise ;
247
+ }
248
+
187
249
/**
188
250
* @inheritDoc
189
251
*/
@@ -201,7 +263,7 @@ export class PersistentConnection extends ServerActions {
201
263
}
202
264
assert (
203
265
query . getQueryParams ( ) . isDefault ( ) ||
204
- ! query . getQueryParams ( ) . loadsAllData ( ) ,
266
+ ! query . getQueryParams ( ) . loadsAllData ( ) ,
205
267
'listen() called for non-default but complete query'
206
268
) ;
207
269
assert (
@@ -221,6 +283,24 @@ export class PersistentConnection extends ServerActions {
221
283
}
222
284
}
223
285
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_ = [ ] ;
296
+ }
297
+ if ( get . onComplete ) {
298
+ get . onComplete ( message ) ;
299
+ }
300
+ }
301
+ ) ;
302
+ }
303
+
224
304
private sendListen_ ( listenSpec : ListenSpec ) {
225
305
const query = listenSpec . query ;
226
306
const pathString = query . path . toString ( ) ;
@@ -273,8 +353,8 @@ export class PersistentConnection extends ServerActions {
273
353
const indexPath = query . path . toString ( ) ;
274
354
warn (
275
355
`Using an unspecified index. Your data will be downloaded and ` +
276
- `filtered on the client. Consider adding ${ indexSpec } at ` +
277
- `${ 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.`
278
358
) ;
279
359
}
280
360
}
@@ -292,7 +372,7 @@ export class PersistentConnection extends ServerActions {
292
372
//If we're connected we want to let the server know to unauthenticate us. If we're not connected, simply delete
293
373
//the credential so we dont become authenticated next time we connect.
294
374
if ( this . connected_ ) {
295
- this . sendRequest ( 'unauth' , { } , ( ) => { } ) ;
375
+ this . sendRequest ( 'unauth' , { } , ( ) => { } ) ;
296
376
}
297
377
}
298
378
@@ -356,7 +436,7 @@ export class PersistentConnection extends ServerActions {
356
436
357
437
assert (
358
438
query . getQueryParams ( ) . isDefault ( ) ||
359
- ! query . getQueryParams ( ) . loadsAllData ( ) ,
439
+ ! query . getQueryParams ( ) . loadsAllData ( ) ,
360
440
'unlisten() called for non-default but complete query'
361
441
) ;
362
442
const listen = this . removeListen_ ( pathString , queryId ) ;
@@ -614,8 +694,8 @@ export class PersistentConnection extends ServerActions {
614
694
} else {
615
695
error (
616
696
'Unrecognized action received from server: ' +
617
- stringify ( action ) +
618
- '\nAre you using the latest client?'
697
+ stringify ( action ) +
698
+ '\nAre you using the latest client?'
619
699
) ;
620
700
}
621
701
}
@@ -950,6 +1030,12 @@ export class PersistentConnection extends ServerActions {
950
1030
request . onComplete
951
1031
) ;
952
1032
}
1033
+
1034
+ for ( let i = 0 ; i < this . outstandingGets_ . length ; i ++ ) {
1035
+ if ( this . outstandingGets_ [ i ] ) {
1036
+ this . sendGet_ ( i ) ;
1037
+ }
1038
+ }
953
1039
}
954
1040
955
1041
/**
0 commit comments