Skip to content

Commit 57a0f2b

Browse files
authored
LimitToLast: back port some changes from android (#2382)
* LimitToLast: back port some changes from android * [AUTOMATED]: Prettier Code Styling * Address comments
1 parent ae31905 commit 57a0f2b

File tree

5 files changed

+31
-112
lines changed

5 files changed

+31
-112
lines changed

packages/firestore/src/core/query.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export class Query {
4848
private memoizedOrderBy: OrderBy[] | null = null;
4949

5050
// The corresponding `Target` of this `Query` instance.
51-
private memorizedTarget: Target | null = null;
51+
private memoizedTarget: Target | null = null;
5252

5353
/**
5454
* Initializes a Query with a path and optional additional query constraints.
@@ -343,9 +343,9 @@ export class Query {
343343
* representation.
344344
*/
345345
toTarget(): Target {
346-
if (!this.memorizedTarget) {
346+
if (!this.memoizedTarget) {
347347
if (this.limitType === LimitType.First) {
348-
this.memorizedTarget = new Target(
348+
this.memoizedTarget = new Target(
349349
this.path,
350350
this.collectionGroup,
351351
this.orderBy,
@@ -374,7 +374,7 @@ export class Query {
374374
: null;
375375

376376
// Now return as a LimitType.First query.
377-
this.memorizedTarget = new Target(
377+
this.memoizedTarget = new Target(
378378
this.path,
379379
this.collectionGroup,
380380
orderBys,
@@ -385,7 +385,7 @@ export class Query {
385385
);
386386
}
387387
}
388-
return this.memorizedTarget!;
388+
return this.memoizedTarget!;
389389
}
390390

391391
private matchesPathAndCollectionGroup(doc: Document): boolean {

packages/firestore/src/local/local_store.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -890,9 +890,10 @@ export class LocalStore {
890890
keepPersistedTargetData: boolean
891891
): Promise<void> {
892892
const targetData = this.targetDataByTarget.get(targetId);
893-
if (!targetData) {
894-
return Promise.resolve();
895-
}
893+
assert(
894+
targetData !== null,
895+
`Tried to release nonexistent target: ${targetId}`
896+
);
896897

897898
const mode = keepPersistedTargetData
898899
? 'readwrite-idempotent'
@@ -917,15 +918,15 @@ export class LocalStore {
917918
return PersistencePromise.forEach(removed, (key: DocumentKey) =>
918919
this.persistence.referenceDelegate.removeReference(txn, key)
919920
).next(() => {
920-
this.persistence.referenceDelegate.removeTarget(txn, targetData);
921+
this.persistence.referenceDelegate.removeTarget(txn, targetData!);
921922
});
922923
} else {
923924
return PersistencePromise.resolve();
924925
}
925926
})
926927
.then(() => {
927928
this.targetDataByTarget = this.targetDataByTarget.remove(targetId);
928-
this.targetIdByTarget.delete(targetData.target);
929+
this.targetIdByTarget.delete(targetData!.target);
929930
});
930931
}
931932

packages/firestore/src/remote/remote_event.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,10 @@ export class TargetChange {
126126
) {}
127127

128128
/**
129-
* HACK: Views require TargetChanges in order to determine whether the view is
130-
* CURRENT, but secondary tabs don't receive remote events. So this method is
131-
* used to create a synthesized TargetChanges that can be used to apply a
132-
* CURRENT status change to a View, for queries executed in a different tab.
129+
* This method is used to create a synthesized TargetChanges that can be used to
130+
* apply a CURRENT status change to a View (for queries executed in a different
131+
* tab) or for new queries (to raise snapshots with correct CURRENT status).
133132
*/
134-
// PORTING NOTE: Multi-tab only
135133
static createSynthesizedTargetChangeForCurrentChange(
136134
targetId: TargetId,
137135
current: boolean

packages/firestore/src/remote/remote_store.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,10 @@ export class RemoteStore implements TargetMetadataProvider {
263263
* not being listened to.
264264
*/
265265
unlisten(targetId: TargetId): void {
266-
if (!objUtils.contains(this.listenTargets, targetId)) {
267-
return;
268-
}
266+
assert(
267+
objUtils.contains(this.listenTargets, targetId),
268+
`unlisten called on target no currently watched: ${targetId}`
269+
);
269270

270271
delete this.listenTargets[targetId];
271272
if (this.watchStream.isOpen()) {

packages/firestore/test/integration/api/query.test.ts

Lines changed: 13 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -143,144 +143,65 @@ apiDescribe('Queries', (persistence: boolean) => {
143143
// Since limitToLast() queries are sent to the backend with a modified
144144
// orderBy() clause, they can map to the same target representation as
145145
// limit() query, even if both queries appear separate to the user.
146-
it('can listen to mirror queries', () => {
146+
it('can listen/unlisten/relisten to mirror queries', () => {
147147
const testDocs = {
148148
a: { k: 'a', sort: 0 },
149149
b: { k: 'b', sort: 1 },
150150
c: { k: 'c', sort: 1 },
151151
d: { k: 'd', sort: 2 }
152152
};
153153
return withTestCollection(persistence, testDocs, async collection => {
154+
// Setup `limit` query
154155
const storeLimitEvent = new EventsAccumulator<firestore.QuerySnapshot>();
155-
collection
156+
let limitUnlisten = collection
156157
.orderBy('sort', 'asc')
157158
.limit(2)
158159
.onSnapshot(storeLimitEvent.storeEvent);
159160

161+
// Setup mirroring `limitToLast` query
160162
const storeLimitToLastEvent = new EventsAccumulator<
161163
firestore.QuerySnapshot
162164
>();
163-
collection
165+
let limitToLastUnlisten = collection
164166
.orderBy('sort', 'desc')
165167
.limitToLast(2)
166168
.onSnapshot(storeLimitToLastEvent.storeEvent);
167169

170+
// Verify both queries get expected results.
168171
let snapshot = await storeLimitEvent.awaitEvent();
169172
expect(toDataArray(snapshot)).to.deep.equal([
170173
{ k: 'a', sort: 0 },
171174
{ k: 'b', sort: 1 }
172175
]);
173-
174176
snapshot = await storeLimitToLastEvent.awaitEvent();
175177
expect(toDataArray(snapshot)).to.deep.equal([
176178
{ k: 'b', sort: 1 },
177179
{ k: 'a', sort: 0 }
178180
]);
179181

180-
await collection.add({ k: 'e', sort: -1 });
181-
snapshot = await storeLimitEvent.awaitEvent();
182-
expect(toDataArray(snapshot)).to.deep.equal([
183-
{ k: 'e', sort: -1 },
184-
{ k: 'a', sort: 0 }
185-
]);
186-
187-
snapshot = await storeLimitToLastEvent.awaitEvent();
188-
expect(toDataArray(snapshot)).to.deep.equal([
189-
{ k: 'a', sort: 0 },
190-
{ k: 'e', sort: -1 }
191-
]);
192-
});
193-
});
194-
195-
it('can unlisten from mirror queries', () => {
196-
const testDocs = {
197-
a: { k: 'a', sort: 0 },
198-
b: { k: 'b', sort: 1 },
199-
c: { k: 'c', sort: 1 },
200-
d: { k: 'd', sort: 2 }
201-
};
202-
return withTestCollection(persistence, testDocs, async collection => {
203-
const storeLimitEvent = new EventsAccumulator<firestore.QuerySnapshot>();
204-
const limitUnlisten = collection
205-
.orderBy('sort', 'asc')
206-
.limit(2)
207-
.onSnapshot(storeLimitEvent.storeEvent);
208-
209-
const storeLimitToLastEvent = new EventsAccumulator<
210-
firestore.QuerySnapshot
211-
>();
212-
const limitToLastUnlisten = collection
213-
.orderBy('sort', 'desc')
214-
.limitToLast(2)
215-
.onSnapshot(storeLimitToLastEvent.storeEvent);
216-
217-
await storeLimitEvent.awaitEvent();
218-
await storeLimitToLastEvent.awaitEvent();
219-
220-
limitUnlisten();
221-
222-
await collection.add({ k: 'e', sort: -1 });
223-
await storeLimitEvent.assertNoAdditionalEvents();
224-
const snapshot = await storeLimitToLastEvent.awaitEvent();
225-
// Check the limitToLast query still functions after the mirroring
226-
// limit query is un-listened.
227-
expect(toDataArray(snapshot)).to.deep.equal([
228-
{ k: 'a', sort: 0 },
229-
{ k: 'e', sort: -1 }
230-
]);
231-
232-
limitToLastUnlisten();
233-
234-
await collection.add({ k: 'f', sort: -1 });
235-
await storeLimitToLastEvent.assertNoAdditionalEvents();
236-
});
237-
});
238-
239-
it('can relisten to mirror queries', () => {
240-
const testDocs = {
241-
a: { k: 'a', sort: 0 },
242-
b: { k: 'b', sort: 1 },
243-
c: { k: 'c', sort: 1 },
244-
d: { k: 'd', sort: 2 }
245-
};
246-
return withTestCollection(persistence, testDocs, async collection => {
247-
const storeLimitEvent = new EventsAccumulator<firestore.QuerySnapshot>();
248-
let limitUnlisten = collection
249-
.orderBy('sort', 'asc')
250-
.limit(2)
251-
.onSnapshot(storeLimitEvent.storeEvent);
252-
253-
const storeLimitToLastEvent = new EventsAccumulator<
254-
firestore.QuerySnapshot
255-
>();
256-
let limitToLastUnlisten = collection
257-
.orderBy('sort', 'desc')
258-
.limitToLast(2)
259-
.onSnapshot(storeLimitToLastEvent.storeEvent);
260-
261-
await storeLimitEvent.awaitEvent();
262-
await storeLimitToLastEvent.awaitEvent();
263-
264182
// Unlisten then relisten limit query.
265183
limitUnlisten();
266184
limitUnlisten = collection
267185
.orderBy('sort', 'asc')
268186
.limit(2)
269187
.onSnapshot(storeLimitEvent.storeEvent);
270-
let snapshot = await storeLimitEvent.awaitEvent();
188+
189+
// Verify `limit` query still works.
190+
snapshot = await storeLimitEvent.awaitEvent();
271191
expect(toDataArray(snapshot)).to.deep.equal([
272192
{ k: 'a', sort: 0 },
273193
{ k: 'b', sort: 1 }
274194
]);
275195

196+
// Add a document that would change the result set.
276197
await collection.add({ k: 'e', sort: -1 });
277-
// Verify limit query results.
198+
199+
// Verify both queries get expected results.
278200
snapshot = await storeLimitEvent.awaitEvent();
279201
expect(toDataArray(snapshot)).to.deep.equal([
280202
{ k: 'e', sort: -1 },
281203
{ k: 'a', sort: 0 }
282204
]);
283-
// Verify limitToLast query results.
284205
snapshot = await storeLimitToLastEvent.awaitEvent();
285206
expect(toDataArray(snapshot)).to.deep.equal([
286207
{ k: 'a', sort: 0 },
@@ -295,14 +216,12 @@ apiDescribe('Queries', (persistence: boolean) => {
295216
.limitToLast(2)
296217
.onSnapshot(storeLimitToLastEvent.storeEvent);
297218

219+
// Verify both queries get expected results.
298220
snapshot = await storeLimitEvent.awaitEvent();
299-
// Checking limit query is still functioning when the mirroring
300-
// limitToLast query is un-listened.
301221
expect(toDataArray(snapshot)).to.deep.equal([
302222
{ k: 'a', sort: -2 },
303223
{ k: 'e', sort: -1 }
304224
]);
305-
306225
snapshot = await storeLimitToLastEvent.awaitEvent();
307226
expect(toDataArray(snapshot)).to.deep.equal([
308227
{ k: 'e', sort: -1 },

0 commit comments

Comments
 (0)