aboutsummaryrefslogtreecommitdiff
path: root/src/cdp/record-store.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/cdp/record-store.ts')
-rw-r--r--src/cdp/record-store.ts61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/cdp/record-store.ts b/src/cdp/record-store.ts
new file mode 100644
index 0000000..04b71ff
--- /dev/null
+++ b/src/cdp/record-store.ts
@@ -0,0 +1,61 @@
+export type DrainPage<T> = {
+ readonly records: T[];
+ readonly total: number;
+ readonly bufferOverflowed: boolean;
+};
+
+export type RecordStore<K, T> = {
+ set(key: K, rec: T): void;
+ get(key: K): T | undefined;
+ delete(key: K): void;
+ values(): IterableIterator<T>;
+ // Takes the overflow flag as it pages, so each drain reports only the loss since the previous one.
+ page(matched: T[], limit: number | undefined): DrainPage<T>;
+ clear(): void;
+};
+
+const MAX_LIMIT = 500;
+const DEFAULT_LIMIT = 50;
+
+export const createRecordStore = <K, T>(capacity: number): RecordStore<K, T> => {
+ const records = new Map<K, T>();
+ let overflowed = false;
+
+ const evictOldestIfFull = (): void => {
+ while (records.size >= capacity) {
+ const oldest = records.keys().next();
+ if (oldest.done) return;
+ records.delete(oldest.value);
+ overflowed = true;
+ }
+ };
+
+ return {
+ set(key, rec) {
+ evictOldestIfFull();
+ records.set(key, rec);
+ },
+ get(key) {
+ return records.get(key);
+ },
+ delete(key) {
+ records.delete(key);
+ },
+ values() {
+ return records.values();
+ },
+ page(matched, limit) {
+ const bufferOverflowed = overflowed;
+ overflowed = false;
+ return {
+ records: matched.slice(-Math.min(limit ?? DEFAULT_LIMIT, MAX_LIMIT)),
+ total: matched.length,
+ bufferOverflowed,
+ };
+ },
+ clear() {
+ records.clear();
+ overflowed = false;
+ },
+ };
+};