Skip to content

Commit acdd4ca

Browse files
committed
review feedback, queue outstanding gets
1 parent 2a947f7 commit acdd4ca

File tree

5 files changed

+84
-32
lines changed

5 files changed

+84
-32
lines changed

.changeset/many-snails-kneel.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
"@firebase/database": patch
2+
"@firebase/database": minor
33
---
44

55
Add a `get` method for database queries that returns server result when connected

packages/database/CHANGELOG.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Unreleased
22

3-
- [changed] Added support for query get operation.
4-
53
## 0.6.13
64

75
### Patch Changes

packages/database/src/api/Query.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ export class Query {
299299
* Get the server-value for this query, or return a cached value if not connected.
300300
*/
301301
get(): Promise<DataSnapshot> {
302-
return this.repo.get(this);
302+
return this.repo.getValue(this);
303303
}
304304

305305
/**

packages/database/src/core/PersistentConnection.ts

Lines changed: 81 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { SDK_VERSION } from './version';
4545

4646
const RECONNECT_MIN_DELAY = 1000;
4747
const RECONNECT_MAX_DELAY_DEFAULT = 60 * 5 * 1000; // 5 minutes in milliseconds (Case: 1858)
48+
const GET_CONNECT_TIMEOUT = 3 * 1000;
4849
const RECONNECT_MAX_DELAY_FOR_ADMINS = 30 * 1000; // 30 seconds for admin clients (likely to be a backend server)
4950
const RECONNECT_DELAY_MULTIPLIER = 1.3;
5051
const RECONNECT_DELAY_RESET_TIMEOUT = 30000; // Reset delay back to MIN_DELAY after being connected for 30sec.
@@ -76,6 +77,12 @@ interface OutstandingPut {
7677
onComplete: (a: string, b?: string) => void;
7778
}
7879

80+
interface OutstandingGet {
81+
action: string;
82+
request: object;
83+
onComplete: (response: { [k: string]: unknown }) => void;
84+
}
85+
7986
/**
8087
* Firebase connection. Abstracts wire protocol and handles reconnecting.
8188
*
@@ -94,7 +101,9 @@ export class PersistentConnection extends ServerActions {
94101
Map</* queryId */ string, ListenSpec>
95102
> = new Map();
96103
private outstandingPuts_: OutstandingPut[] = [];
104+
private outstandingGets_: OutstandingGet[] = [];
97105
private outstandingPutCount_ = 0;
106+
private outstandingGetCount_ = 0;
98107
private onDisconnectRequestQueue_: OnDisconnectRequest[] = [];
99108
private connected_ = false;
100109
private reconnectDelay_ = RECONNECT_MIN_DELAY;
@@ -186,15 +195,55 @@ export class PersistentConnection extends ServerActions {
186195
}
187196

188197
get(query: Query): Promise<string> {
189-
const req: { [k: string]: unknown } = {
198+
const deferred = new Deferred<string>();
199+
const request = {
190200
p: query.path.toString(),
191201
q: query.queryObject()
192202
};
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+
193242
if (this.connected_) {
194-
return this.sendGet_(req);
195-
} else {
196-
return Promise.reject(new Error('Client is offline'));
243+
this.sendGet_(index);
197244
}
245+
246+
return deferred.promise;
198247
}
199248

200249
/**
@@ -214,7 +263,7 @@ export class PersistentConnection extends ServerActions {
214263
}
215264
assert(
216265
query.getQueryParams().isDefault() ||
217-
!query.getQueryParams().loadsAllData(),
266+
!query.getQueryParams().loadsAllData(),
218267
'listen() called for non-default but complete query'
219268
);
220269
assert(
@@ -234,23 +283,22 @@ export class PersistentConnection extends ServerActions {
234283
}
235284
}
236285

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_ = [];
251296
}
252-
});
253-
});
297+
if (get.onComplete) {
298+
get.onComplete(message);
299+
}
300+
}
301+
);
254302
}
255303

256304
private sendListen_(listenSpec: ListenSpec) {
@@ -305,8 +353,8 @@ export class PersistentConnection extends ServerActions {
305353
const indexPath = query.path.toString();
306354
warn(
307355
`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.`
310358
);
311359
}
312360
}
@@ -324,7 +372,7 @@ export class PersistentConnection extends ServerActions {
324372
//If we're connected we want to let the server know to unauthenticate us. If we're not connected, simply delete
325373
//the credential so we dont become authenticated next time we connect.
326374
if (this.connected_) {
327-
this.sendRequest('unauth', {}, () => {});
375+
this.sendRequest('unauth', {}, () => { });
328376
}
329377
}
330378

@@ -388,7 +436,7 @@ export class PersistentConnection extends ServerActions {
388436

389437
assert(
390438
query.getQueryParams().isDefault() ||
391-
!query.getQueryParams().loadsAllData(),
439+
!query.getQueryParams().loadsAllData(),
392440
'unlisten() called for non-default but complete query'
393441
);
394442
const listen = this.removeListen_(pathString, queryId);
@@ -646,8 +694,8 @@ export class PersistentConnection extends ServerActions {
646694
} else {
647695
error(
648696
'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?'
651699
);
652700
}
653701
}
@@ -982,6 +1030,12 @@ export class PersistentConnection extends ServerActions {
9821030
request.onComplete
9831031
);
9841032
}
1033+
1034+
for (let i = 0; i < this.outstandingGets_.length; i++) {
1035+
if (this.outstandingGets_[i]) {
1036+
this.sendGet_(i);
1037+
}
1038+
}
9851039
}
9861040

9871041
/**

packages/database/src/core/Repo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ export class Repo {
297297
return this.nextWriteId_++;
298298
}
299299

300-
get(query: Query): Promise<DataSnapshot> {
300+
getValue(query: Query): Promise<DataSnapshot> {
301301
return this.server_.get(query).then(
302302
payload => {
303303
const node = nodeFromJSON(payload as string);

0 commit comments

Comments
 (0)