Throw if a PIT finder collects too much responses

This commit is contained in:
Rudolf Meijering 2023-09-28 09:57:49 +02:00
parent 34c084d65a
commit b651e4f132
2 changed files with 16 additions and 5 deletions

View file

@ -43,10 +43,11 @@ export class PointInTimeFinder<T = unknown, A = unknown>
{
readonly #log: Logger;
readonly #client: SavedObjectsPointInTimeFinderClient;
readonly #findOptions: SavedObjectsFindOptions;
readonly #findOptions: SavedObjectsCreatePointInTimeFinderOptions;
readonly #internalOptions: SavedObjectsFindInternalOptions | undefined;
#open: boolean = false;
#pitId?: string;
#totalCollectedResponseSize: number = 0;
constructor(
findOptions: SavedObjectsCreatePointInTimeFinderOptions,
@ -59,6 +60,8 @@ export class PointInTimeFinder<T = unknown, A = unknown>
// Default to 1000 items per page as a tradeoff between
// speed and memory consumption.
perPage: 1000,
// Default to 256MB to protect the event loop and prevent the server against OOM errors
maxTotalResponseSize: 268435456,
...findOptions,
};
}
@ -83,6 +86,7 @@ export class PointInTimeFinder<T = unknown, A = unknown>
searchAfter: lastHitSortValue,
});
this.#pitId = results.pit_id;
this.#totalCollectedResponseSize += Buffer.byteLength(JSON.stringify(results));
lastResultsCount = results.saved_objects.length;
lastHitSortValue = this.getLastHitSortValue(results);
@ -93,10 +97,17 @@ export class PointInTimeFinder<T = unknown, A = unknown>
await this.close();
}
// Close PIT if we've collected more than maxTotalResponseSize
if (this.#totalCollectedResponseSize > this.#findOptions.maxTotalResponseSize!) {
await this.close();
throw new Error(
'The point in time finder has collected more than the maximum total response size'
);
}
yield results;
// We've reached the end when there are fewer hits than our perPage size,
// or when `close()` has been called.
} while (this.#open && lastResultsCount >= this.#findOptions.perPage!);
// `close()` has been called, stop yielding results
} while (this.#open);
return;
}

View file

@ -17,7 +17,7 @@ import type { ISavedObjectsRepository } from '../saved_objects_repository';
export type SavedObjectsCreatePointInTimeFinderOptions = Omit<
SavedObjectsFindOptions,
'page' | 'pit' | 'searchAfter'
>;
> & { maxTotalResponseSize?: number };
/**
* Point-in-time finder client.