Skip to content

Query get() method for RTDB #3812

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Nov 17, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
86363d6
Query get() method for RTDB
jmwski Sep 18, 2020
0abd55c
Fix yarn test
jmwski Sep 18, 2020
437b8a7
Call onDataUpdate_ to simulater server push
jmwski Sep 18, 2020
8b289f8
Run yarn prettier
jmwski Sep 18, 2020
153dbcf
cleanup
jmwski Sep 18, 2020
61665bf
Add basic tests for get
jmwski Sep 23, 2020
9b2cf00
remove callback arguments to get()
jmwski Sep 23, 2020
ab34805
get rid of todo
jmwski Sep 23, 2020
f20c903
Use promises instead + caching test
jmwski Oct 6, 2020
d9530ee
Uncomment tests
jmwski Oct 6, 2020
48c6d39
test rename
jmwski Oct 6, 2020
2bae15b
fix checks
jmwski Oct 6, 2020
578f9ca
x
jmwski Oct 9, 2020
b6cef9f
actually called repo.get
jmwski Oct 9, 2020
5802286
more fixes
jmwski Oct 9, 2020
5eae993
remove extra diff
jmwski Oct 9, 2020
2a7f81f
fixup query tests
jmwski Oct 12, 2020
00a0959
more test fixes
jmwski Oct 12, 2020
7ef7e69
use deep.equal in tests
jmwski Oct 12, 2020
272587f
Undo package.json changes
jmwski Oct 12, 2020
377a263
remove unused imports
jmwski Oct 12, 2020
d400785
remove accidental push
jmwski Oct 12, 2020
b19f026
more unused imports cleanup
jmwski Oct 12, 2020
c0160b6
Merge branch 'master' into jw/rtdb-query-get
jmwski Oct 12, 2020
c050c0d
lint stuff
jmwski Oct 12, 2020
bdc10ca
point CI to emulator v4.6.0
jmwski Oct 13, 2020
950de5a
address review feedback
jmwski Oct 21, 2020
fdc379d
undo package.json change
jmwski Oct 21, 2020
b81d898
review feedback
jmwski Oct 22, 2020
483cedc
update changelog
jmwski Oct 22, 2020
a7b0e67
Create many-snails-kneel.md
jmwski Oct 22, 2020
2a947f7
import fixes
jmwski Oct 22, 2020
acdd4ca
review feedback, queue outstanding gets
jmwski Nov 4, 2020
c0f627c
lint
jmwski Nov 4, 2020
f6dcb38
review
jmwski Nov 12, 2020
26703f5
remove extra comment
jmwski Nov 12, 2020
008e6fb
Update .changeset/many-snails-kneel.md
jmwski Nov 17, 2020
2643f8a
Update packages/database/src/core/Repo.ts
jmwski Nov 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/many-snails-kneel.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"@firebase/database": patch
"@firebase/database": minor
---

Add a `get` method for database queries that returns server result when connected
2 changes: 0 additions & 2 deletions packages/database/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Unreleased

- [changed] Added support for query get operation.

## 0.6.13

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/database/src/api/Query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ export class Query {
* Get the server-value for this query, or return a cached value if not connected.
*/
get(): Promise<DataSnapshot> {
return this.repo.get(this);
return this.repo.getValue(this);
}

/**
Expand Down
108 changes: 81 additions & 27 deletions packages/database/src/core/PersistentConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import { SDK_VERSION } from './version';

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

interface OutstandingGet {
action: string;
request: object;
onComplete: (response: { [k: string]: unknown }) => void;
}

/**
* Firebase connection. Abstracts wire protocol and handles reconnecting.
*
Expand All @@ -94,7 +101,9 @@ export class PersistentConnection extends ServerActions {
Map</* queryId */ string, ListenSpec>
> = new Map();
private outstandingPuts_: OutstandingPut[] = [];
private outstandingGets_: OutstandingGet[] = [];
private outstandingPutCount_ = 0;
private outstandingGetCount_ = 0;
private onDisconnectRequestQueue_: OnDisconnectRequest[] = [];
private connected_ = false;
private reconnectDelay_ = RECONNECT_MIN_DELAY;
Expand Down Expand Up @@ -186,15 +195,55 @@ export class PersistentConnection extends ServerActions {
}

get(query: Query): Promise<string> {
const req: { [k: string]: unknown } = {
const deferred = new Deferred<string>();
const request = {
p: query.path.toString(),
q: query.queryObject()
};
const outstandingGet = {
action: 'g',
request,
onComplete: (message: { [k: string]: unknown }) => {
const payload = message['d'] as string;
if (message['s'] === 'ok') {
this.onDataUpdate_(
request['p'],
payload,
/*isMerge*/ false,
/*tag*/ null
);
deferred.resolve(payload);
} else {
deferred.reject(payload);
}
}
};
this.outstandingGets_.push(outstandingGet);
this.outstandingGetCount_++;
const index = this.outstandingGets_.length - 1;

if (!this.connected_) {
const self = this;
setTimeout(function () {
const get = self.outstandingGets_[index];
if (get === undefined || outstandingGet !== get) {
return;
}
delete self.outstandingGets_[index];
self.outstandingGetCount_--;
if (self.outstandingGetCount_ === 0) {
self.outstandingGets_ = [];
}
self.log_('get ' + index + ' timed out on connection');
deferred.reject(new Error('Client is offline.'));
}, GET_CONNECT_TIMEOUT);
}

if (this.connected_) {
return this.sendGet_(req);
} else {
return Promise.reject(new Error('Client is offline'));
this.sendGet_(index);
}

return deferred.promise;
}

/**
Expand All @@ -214,7 +263,7 @@ export class PersistentConnection extends ServerActions {
}
assert(
query.getQueryParams().isDefault() ||
!query.getQueryParams().loadsAllData(),
!query.getQueryParams().loadsAllData(),
'listen() called for non-default but complete query'
);
assert(
Expand All @@ -234,23 +283,22 @@ export class PersistentConnection extends ServerActions {
}
}

private sendGet_(request: object): Promise<string> {
return new Promise((resolve, reject) => {
this.sendRequest('g', request, (message: { [k: string]: unknown }) => {
const payload = message['d'] as string;
if (message['s'] === 'ok') {
this.onDataUpdate_(
request['p'],
payload,
/*isMerge*/ false,
/*tag*/ null
);
resolve(payload);
} else {
reject(payload);
private sendGet_(index: number) {
const get = this.outstandingGets_[index];
this.sendRequest(
get.action,
get.request,
(message: { [k: string]: unknown }) => {
delete this.outstandingGets_[index];
this.outstandingGetCount_--;
if (this.outstandingGetCount_ === 0) {
this.outstandingGets_ = [];
}
});
});
if (get.onComplete) {
get.onComplete(message);
}
}
);
}

private sendListen_(listenSpec: ListenSpec) {
Expand Down Expand Up @@ -305,8 +353,8 @@ export class PersistentConnection extends ServerActions {
const indexPath = query.path.toString();
warn(
`Using an unspecified index. Your data will be downloaded and ` +
`filtered on the client. Consider adding ${indexSpec} at ` +
`${indexPath} to your security rules for better performance.`
`filtered on the client. Consider adding ${indexSpec} at ` +
`${indexPath} to your security rules for better performance.`
);
}
}
Expand All @@ -324,7 +372,7 @@ export class PersistentConnection extends ServerActions {
//If we're connected we want to let the server know to unauthenticate us. If we're not connected, simply delete
//the credential so we dont become authenticated next time we connect.
if (this.connected_) {
this.sendRequest('unauth', {}, () => {});
this.sendRequest('unauth', {}, () => { });
}
}

Expand Down Expand Up @@ -388,7 +436,7 @@ export class PersistentConnection extends ServerActions {

assert(
query.getQueryParams().isDefault() ||
!query.getQueryParams().loadsAllData(),
!query.getQueryParams().loadsAllData(),
'unlisten() called for non-default but complete query'
);
const listen = this.removeListen_(pathString, queryId);
Expand Down Expand Up @@ -646,8 +694,8 @@ export class PersistentConnection extends ServerActions {
} else {
error(
'Unrecognized action received from server: ' +
stringify(action) +
'\nAre you using the latest client?'
stringify(action) +
'\nAre you using the latest client?'
);
}
}
Expand Down Expand Up @@ -982,6 +1030,12 @@ export class PersistentConnection extends ServerActions {
request.onComplete
);
}

for (let i = 0; i < this.outstandingGets_.length; i++) {
if (this.outstandingGets_[i]) {
this.sendGet_(i);
}
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/database/src/core/Repo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ export class Repo {
return this.nextWriteId_++;
}

get(query: Query): Promise<DataSnapshot> {
getValue(query: Query): Promise<DataSnapshot> {
return this.server_.get(query).then(
payload => {
const node = nodeFromJSON(payload as string);
Expand Down