Skip to content

Commit e1b3014

Browse files
committed
Undid change
1 parent 76dfbf6 commit e1b3014

File tree

1 file changed

+52
-21
lines changed

1 file changed

+52
-21
lines changed

packages/database/src/core/Repo.ts

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import {
2424
stringify
2525
} from '@firebase/util';
2626

27+
import { ValueEventRegistration } from '../api/Reference_impl';
28+
2729
import { AppCheckTokenProvider } from './AppCheckTokenProvider';
2830
import { AuthTokenProvider } from './AuthTokenProvider';
2931
import { PersistentConnection } from './PersistentConnection';
@@ -61,7 +63,7 @@ import {
6163
syncTreeCalcCompleteEventCache,
6264
syncTreeGetServerValue,
6365
syncTreeRemoveEventRegistration,
64-
syncTreeRegisterQuery
66+
syncTreeTagForQuery
6567
} from './SyncTree';
6668
import { Indexable } from './util/misc';
6769
import {
@@ -452,14 +454,18 @@ function repoGetNextWriteId(repo: Repo): number {
452454
* belonging to active listeners. If they are found, such values
453455
* are considered to be the most up-to-date.
454456
*
455-
* If the client is not connected, this method will try to
456-
* establish a connection and request the value for `query`. If
457-
* the client is not able to retrieve the query result, it reports
458-
* an error.
457+
* If the client is not connected, this method will wait until the
458+
* repo has established a connection and then request the value for `query`.
459+
* If the client is not able to retrieve the query result for another reason,
460+
* it reports an error.
459461
*
460462
* @param query - The query to surface a value for.
461463
*/
462-
export function repoGetValue(repo: Repo, query: QueryContext): Promise<Node> {
464+
export function repoGetValue(
465+
repo: Repo,
466+
query: QueryContext,
467+
eventRegistration: ValueEventRegistration
468+
): Promise<Node> {
463469
// Only active queries are cached. There is no persisted cache.
464470
const cached = syncTreeGetServerValue(repo.serverSyncTree_, query);
465471
if (cached != null) {
@@ -470,32 +476,57 @@ export function repoGetValue(repo: Repo, query: QueryContext): Promise<Node> {
470476
const node = nodeFromJSON(payload).withIndex(
471477
query._queryParams.getIndex()
472478
);
473-
// if this is a filtered query, then overwrite at path
479+
/**
480+
* Below we simulate the actions of an `onlyOnce` `onValue()` event where:
481+
* Add an event registration,
482+
* Update data at the path,
483+
* Raise any events,
484+
* Cleanup the SyncTree
485+
*/
486+
syncTreeAddEventRegistration(
487+
repo.serverSyncTree_,
488+
query,
489+
eventRegistration,
490+
true
491+
);
492+
let events: Event[];
474493
if (query._queryParams.loadsAllData()) {
475-
syncTreeApplyServerOverwrite(repo.serverSyncTree_, query._path, node);
494+
events = syncTreeApplyServerOverwrite(
495+
repo.serverSyncTree_,
496+
query._path,
497+
node
498+
);
476499
} else {
477-
// Simulate `syncTreeAddEventRegistration` without events/listener setup.
478-
// We do this (along with the syncTreeRemoveEventRegistration` below) so that
479-
// `repoGetValue` results have the same cache effects as initial listener(s)
480-
// updates.
481-
const tag = syncTreeRegisterQuery(repo.serverSyncTree_, query);
482-
syncTreeApplyTaggedQueryOverwrite(
500+
const tag = syncTreeTagForQuery(repo.serverSyncTree_, query);
501+
events = syncTreeApplyTaggedQueryOverwrite(
483502
repo.serverSyncTree_,
484503
query._path,
485504
node,
486505
tag
487506
);
488-
// Call `syncTreeRemoveEventRegistration` with a null event registration, since there is none.
489-
// Note: The below code essentially unregisters the query and cleans up any views/syncpoints temporarily created above.
490507
}
491-
const cancels = syncTreeRemoveEventRegistration(
508+
/*
509+
* We need to raise events in the scenario where `get()` is called at a parent path, and
510+
* while the `get()` is pending, `onValue` is called at a child location. While get() is waiting
511+
* for the data, `onValue` will register a new event. Then, get() will come back, and update the syncTree
512+
* and its corresponding serverCache, including the child location where `onValue` is called. Then,
513+
* `onValue` will receive the event from the server, but look at the syncTree and see that the data received
514+
* from the server is already at the SyncPoint, and so the `onValue` callback will never get fired.
515+
* Calling `eventQueueRaiseEventsForChangedPath()` is the correct way to propagate the events and
516+
* ensure the corresponding child events will get fired.
517+
*/
518+
eventQueueRaiseEventsForChangedPath(
519+
repo.eventQueue_,
520+
query._path,
521+
events
522+
);
523+
syncTreeRemoveEventRegistration(
492524
repo.serverSyncTree_,
493525
query,
494-
null
526+
eventRegistration,
527+
null,
528+
true
495529
);
496-
if (cancels.length > 0) {
497-
repoLog(repo, 'unexpected cancel events in repoGetValue');
498-
}
499530
return node;
500531
},
501532
err => {

0 commit comments

Comments
 (0)