Skip to content

Commit ab94092

Browse files
authored
fix: Use correct limit when retrying a limit query stream with a cursor (#2203)
* fix: Use correct limit when retrying a limit query stream with a cursor When a query is streamed and the stream fails after receiving part of the result set, the client retries the stream with a cursor. If the original query has a limit, the retry logic should use a modified limit for the remainder of the stream to ensure the final result contains the correct number of documents. * Update recursiveDelete test. * Add tests. * Address feedback. * Address feedback (2).
1 parent 1775ce6 commit ab94092

File tree

3 files changed

+360
-67
lines changed

3 files changed

+360
-67
lines changed

dev/src/reference/query-util.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ export class QueryUtil<
181181
const startTime = Date.now();
182182
const isExplain = explainOptions !== undefined;
183183

184+
let numDocumentsReceived = 0;
184185
let lastReceivedDocument: QueryDocumentSnapshot<
185186
AppModelType,
186187
DbModelType
@@ -239,6 +240,7 @@ export class QueryUtil<
239240
);
240241
}
241242

243+
++numDocumentsReceived;
242244
callback(undefined, output);
243245

244246
if (proto.done) {
@@ -317,6 +319,12 @@ export class QueryUtil<
317319
stream.destroy(err);
318320
streamActive.resolve(/* active= */ false);
319321
} else if (lastReceivedDocument && retryWithCursor) {
322+
if (query instanceof VectorQuery) {
323+
throw new Error(
324+
'Unimplemented: Vector query does not support cursors yet.'
325+
);
326+
}
327+
320328
logger(
321329
'Query._stream',
322330
tag,
@@ -330,12 +338,30 @@ export class QueryUtil<
330338
// the query cursor. Note that we do not use backoff here. The
331339
// call to `requestStream()` will backoff should the restart
332340
// fail before delivering any results.
341+
let newQuery: Query<AppModelType, DbModelType>;
342+
if (!this._queryOptions.limit) {
343+
newQuery = query;
344+
} else {
345+
const newLimit =
346+
this._queryOptions.limit - numDocumentsReceived;
347+
if (
348+
this._queryOptions.limitType === undefined ||
349+
this._queryOptions.limitType === LimitType.First
350+
) {
351+
newQuery = query.limit(newLimit);
352+
} else {
353+
newQuery = query.limitToLast(newLimit);
354+
}
355+
}
356+
333357
if (this._queryOptions.requireConsistency) {
334-
request = query
358+
request = newQuery
335359
.startAfter(lastReceivedDocument)
336360
.toProto(lastReceivedDocument.readTime);
337361
} else {
338-
request = query.startAfter(lastReceivedDocument).toProto();
362+
request = newQuery
363+
.startAfter(lastReceivedDocument)
364+
.toProto();
339365
}
340366

341367
// Set lastReceivedDocument to null before each retry attempt to ensure the retry makes progress

0 commit comments

Comments
 (0)