@lensjs/core 2.2.2 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abstracts/store.cjs +3 -0
- package/dist/abstracts/store.d.cts +3 -1
- package/dist/abstracts/store.d.ts +3 -1
- package/dist/abstracts/store.js +3 -0
- package/dist/core/lens.cjs +151 -24
- package/dist/core/lens.d.cts +3 -2
- package/dist/core/lens.d.ts +3 -2
- package/dist/core/lens.js +151 -24
- package/dist/{index-CMvlRWcQ.d.cts → index-CZsa0Zcm.d.ts} +3 -1
- package/dist/{index-CMvlRWcQ.d.ts → index-QmOJr0K-.d.cts} +3 -1
- package/dist/index.cjs +199 -29
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +198 -29
- package/dist/mixins/queued_store.cjs +114 -0
- package/dist/mixins/queued_store.d.cts +38 -0
- package/dist/mixins/queued_store.d.ts +38 -0
- package/dist/mixins/queued_store.js +79 -0
- package/dist/stores/better_sqlite.cjs +36 -0
- package/dist/stores/better_sqlite.d.cts +3 -0
- package/dist/stores/better_sqlite.d.ts +3 -0
- package/dist/stores/better_sqlite.js +36 -0
- package/dist/stores/index.cjs +129 -2
- package/dist/stores/index.d.cts +2 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/index.js +127 -1
- package/dist/stores/queued_sqlite.cjs +313 -0
- package/dist/stores/queued_sqlite.d.cts +43 -0
- package/dist/stores/queued_sqlite.d.ts +43 -0
- package/dist/stores/queued_sqlite.js +280 -0
- package/dist/types/index.d.cts +16 -2
- package/dist/types/index.d.ts +16 -2
- package/dist/ui/assets/{CacheActionBadge-CL10Xlw7.js → CacheActionBadge-BB4uokI1.js} +1 -1
- package/dist/ui/assets/CacheEntriesTable-B8cUXhos.js +1 -0
- package/dist/ui/assets/CacheEntryContainer-WkdnGvnu.js +2 -0
- package/dist/ui/assets/CacheEntryDetails-BeZnoIpm.js +1 -0
- package/dist/ui/assets/CacheEntryDetailsContainer-DI0mEvpu.js +2 -0
- package/dist/ui/assets/ExceptionContainer-YNcR0F5U.js +2 -0
- package/dist/ui/assets/{ExceptionDetails-Bzj8OZ70.js → ExceptionDetails-BKHzv6hf.js} +1 -1
- package/dist/ui/assets/ExceptionDetailsContainer-CJHILjb3.js +2 -0
- package/dist/ui/assets/{ExceptionTable-BkFSFGbn.js → ExceptionTable-DzBmQLLa.js} +1 -1
- package/dist/ui/assets/JsonViewer-D-KPN089.js +1 -0
- package/dist/ui/assets/{LoadMore-Du7yL-Hr.js → LoadMore-CLPR6Zd4.js} +1 -1
- package/dist/ui/assets/QueriesContainer-B_PmBkHR.js +2 -0
- package/dist/ui/assets/{QueryDetailsContainer-BtbvRyBf.js → QueryDetailsContainer-Cqj3E6Dr.js} +16 -26
- package/dist/ui/assets/{QueryTable-tJVEncUM.js → QueryTable-DmWdZSnJ.js} +1 -1
- package/dist/ui/assets/{RequestDetails-C6tqSqg9.js → RequestDetails-CF338Kcv.js} +1 -1
- package/dist/ui/assets/{RequestDetailsContainer---KvdZKp.js → RequestDetailsContainer-aW4GLool.js} +2 -2
- package/dist/ui/assets/{RequestsContainer-Bogurt1b.js → RequestsContainer-DdLSvAbl.js} +2 -2
- package/dist/ui/assets/{RequetsTable-BMrYHd0d.js → RequetsTable-Bdp_PhGU.js} +1 -1
- package/dist/ui/assets/{StatusCode-DpZO0dUJ.js → StatusCode-C605nHvd.js} +1 -1
- package/dist/ui/assets/TabbedDataViewer-ofhEq_Wj.js +2 -0
- package/dist/ui/assets/{Table-BtkmKVTF.js → Table-kak5sL5X.js} +1 -1
- package/dist/ui/assets/{columns-D_NhXbk6.js → columns-BEyDhUNq.js} +1 -1
- package/dist/ui/assets/{columns-DlGaMv5C.js → columns-Bu5psHyp.js} +1 -1
- package/dist/ui/assets/{columns-DF7BR0z_.js → columns-BvIUTkjN.js} +1 -1
- package/dist/ui/assets/copy-DzXuP4eO.js +11 -0
- package/dist/ui/assets/index-CsnKQ5Mh.css +1 -0
- package/dist/ui/assets/{index-EQXljT95.js → index-TW_-MgRG.js} +25 -25
- package/dist/ui/assets/{useCacheEntries-jC9XYsV_.js → useCacheEntries-Pvte_aNc.js} +1 -1
- package/dist/ui/assets/{useExceptions-CwwK33mG.js → useExceptions-P3cnURvN.js} +1 -1
- package/dist/ui/assets/{useLensApi-CPvDlyGv.js → useLensApi-BFdsfrzR.js} +1 -1
- package/dist/ui/assets/{useLoadMore-C2bqGSaL.js → useLoadMore-JCWak1Dg.js} +1 -1
- package/dist/ui/assets/{useQueries-CzbIajH6.js → useQueries-CNquFtm0.js} +1 -1
- package/dist/ui/index.html +2 -2
- package/dist/utils/compose.cjs +32 -0
- package/dist/utils/compose.d.cts +11 -0
- package/dist/utils/compose.d.ts +11 -0
- package/dist/utils/compose.js +7 -0
- package/dist/utils/index.cjs +10 -1
- package/dist/utils/index.d.cts +3 -1
- package/dist/utils/index.d.ts +3 -1
- package/dist/utils/index.js +9 -1
- package/dist/watchers/index.cjs +45 -5
- package/dist/watchers/index.js +45 -5
- package/dist/watchers/request_watcher.cjs +45 -5
- package/dist/watchers/request_watcher.d.cts +12 -1
- package/dist/watchers/request_watcher.d.ts +12 -1
- package/dist/watchers/request_watcher.js +45 -5
- package/package.json +2 -1
- package/dist/ui/assets/CacheEntriesTable-DuLoeu0e.js +0 -1
- package/dist/ui/assets/CacheEntryContainer-DqHm-jQl.js +0 -2
- package/dist/ui/assets/CacheEntryDetails-k-74LsSb.js +0 -1
- package/dist/ui/assets/CacheEntryDetailsContainer-DTI7gtUq.js +0 -2
- package/dist/ui/assets/ExceptionContainer-0dCs6QMQ.js +0 -2
- package/dist/ui/assets/ExceptionDetailsContainer-Bim0gTpE.js +0 -2
- package/dist/ui/assets/QueriesContainer-5xlqsYl0.js +0 -2
- package/dist/ui/assets/TabbedDataViewer-C60W9bqz.js +0 -1
- package/dist/ui/assets/index-CMJVCuvo.css +0 -1
|
@@ -36,6 +36,9 @@ module.exports = __toCommonJS(better_sqlite_exports);
|
|
|
36
36
|
|
|
37
37
|
// src/abstracts/store.ts
|
|
38
38
|
var Store = class {
|
|
39
|
+
storeConfig;
|
|
40
|
+
constructor(...args) {
|
|
41
|
+
}
|
|
39
42
|
getAllExceptions(_paginationParams) {
|
|
40
43
|
return this.defaultMinimalPaginate();
|
|
41
44
|
}
|
|
@@ -66,6 +69,8 @@ var import_crypto = require("crypto");
|
|
|
66
69
|
var import_libsql = __toESM(require("libsql"), 1);
|
|
67
70
|
var import_date = require("@lensjs/date");
|
|
68
71
|
var TABLE_NAME = "lens_entries";
|
|
72
|
+
var BYTES_IN_GB = 1024 * 1024 * 1024;
|
|
73
|
+
var PRUNE_BATCH_SIZE = 1e3;
|
|
69
74
|
var BetterSqliteStore = class extends Store {
|
|
70
75
|
connection;
|
|
71
76
|
async initialize() {
|
|
@@ -87,6 +92,7 @@ var BetterSqliteStore = class extends Store {
|
|
|
87
92
|
lens_entry_id: entry.requestId || null,
|
|
88
93
|
minimalData: this.stringifyData(entry.minimal_data ?? {})
|
|
89
94
|
});
|
|
95
|
+
this.maybePruneDatabase();
|
|
90
96
|
}
|
|
91
97
|
async getAllQueries(pagination) {
|
|
92
98
|
return await this.paginate("query" /* QUERY */, pagination);
|
|
@@ -162,6 +168,36 @@ var BetterSqliteStore = class extends Store {
|
|
|
162
168
|
this.connection.exec(createIndex);
|
|
163
169
|
this.connection.exec(lensEntryIdIndex);
|
|
164
170
|
}
|
|
171
|
+
maybePruneDatabase() {
|
|
172
|
+
const maxGb = this.storeConfig?.dbMaxSizeGb;
|
|
173
|
+
const pruneGb = this.storeConfig?.dbPruneSizeGb;
|
|
174
|
+
if (!maxGb || !pruneGb) return;
|
|
175
|
+
const maxBytes = maxGb * BYTES_IN_GB;
|
|
176
|
+
const pruneBytes = pruneGb * BYTES_IN_GB;
|
|
177
|
+
if (maxBytes <= 0 || pruneBytes <= 0) return;
|
|
178
|
+
const targetBytes = Math.max(0, maxBytes - pruneBytes);
|
|
179
|
+
let usedBytes = this.getDatabaseUsedBytes();
|
|
180
|
+
if (usedBytes < maxBytes) return;
|
|
181
|
+
while (usedBytes > targetBytes) {
|
|
182
|
+
const deletedRows = this.deleteOldestEntries(PRUNE_BATCH_SIZE);
|
|
183
|
+
if (deletedRows === 0) break;
|
|
184
|
+
usedBytes = this.getDatabaseUsedBytes();
|
|
185
|
+
}
|
|
186
|
+
this.connection.exec("PRAGMA wal_checkpoint(TRUNCATE);");
|
|
187
|
+
}
|
|
188
|
+
getDatabaseUsedBytes() {
|
|
189
|
+
const pageSizeResult = this.connection.prepare("PRAGMA page_size;").get();
|
|
190
|
+
const pageCountResult = this.connection.prepare("PRAGMA page_count;").get();
|
|
191
|
+
const freelistCountResult = this.connection.prepare("PRAGMA freelist_count;").get();
|
|
192
|
+
const usedPages = pageCountResult.page_count - freelistCountResult.freelist_count;
|
|
193
|
+
return usedPages * pageSizeResult.page_size;
|
|
194
|
+
}
|
|
195
|
+
deleteOldestEntries(batchSize) {
|
|
196
|
+
const result = this.connection.prepare(
|
|
197
|
+
`DELETE FROM ${TABLE_NAME} WHERE id IN (SELECT id FROM ${TABLE_NAME} ORDER BY created_at ASC LIMIT ?)`
|
|
198
|
+
).run(batchSize);
|
|
199
|
+
return Number(result.changes ?? 0);
|
|
200
|
+
}
|
|
165
201
|
mapRow(row, includeFullData = true) {
|
|
166
202
|
let data = includeFullData ? JSON.parse(row.data) : {};
|
|
167
203
|
if (!includeFullData) {
|
|
@@ -59,6 +59,9 @@ declare class BetterSqliteStore extends Store {
|
|
|
59
59
|
count(type: WatcherTypeEnum): Promise<number>;
|
|
60
60
|
find(type: WatcherTypeEnum, id: string): Promise<LensEntry | null>;
|
|
61
61
|
private setupSchema;
|
|
62
|
+
private maybePruneDatabase;
|
|
63
|
+
private getDatabaseUsedBytes;
|
|
64
|
+
private deleteOldestEntries;
|
|
62
65
|
protected mapRow(row: any, includeFullData?: boolean): LensEntry;
|
|
63
66
|
protected mapRows(rows: any[], includeFullData?: boolean): LensEntry[];
|
|
64
67
|
protected getSelectedColumns(includeFullData?: boolean): string;
|
|
@@ -59,6 +59,9 @@ declare class BetterSqliteStore extends Store {
|
|
|
59
59
|
count(type: WatcherTypeEnum): Promise<number>;
|
|
60
60
|
find(type: WatcherTypeEnum, id: string): Promise<LensEntry | null>;
|
|
61
61
|
private setupSchema;
|
|
62
|
+
private maybePruneDatabase;
|
|
63
|
+
private getDatabaseUsedBytes;
|
|
64
|
+
private deleteOldestEntries;
|
|
62
65
|
protected mapRow(row: any, includeFullData?: boolean): LensEntry;
|
|
63
66
|
protected mapRows(rows: any[], includeFullData?: boolean): LensEntry[];
|
|
64
67
|
protected getSelectedColumns(includeFullData?: boolean): string;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// src/abstracts/store.ts
|
|
2
2
|
var Store = class {
|
|
3
|
+
storeConfig;
|
|
4
|
+
constructor(...args) {
|
|
5
|
+
}
|
|
3
6
|
getAllExceptions(_paginationParams) {
|
|
4
7
|
return this.defaultMinimalPaginate();
|
|
5
8
|
}
|
|
@@ -30,6 +33,8 @@ import { randomUUID } from "crypto";
|
|
|
30
33
|
import Database from "libsql";
|
|
31
34
|
import { nowISO } from "@lensjs/date";
|
|
32
35
|
var TABLE_NAME = "lens_entries";
|
|
36
|
+
var BYTES_IN_GB = 1024 * 1024 * 1024;
|
|
37
|
+
var PRUNE_BATCH_SIZE = 1e3;
|
|
33
38
|
var BetterSqliteStore = class extends Store {
|
|
34
39
|
connection;
|
|
35
40
|
async initialize() {
|
|
@@ -51,6 +56,7 @@ var BetterSqliteStore = class extends Store {
|
|
|
51
56
|
lens_entry_id: entry.requestId || null,
|
|
52
57
|
minimalData: this.stringifyData(entry.minimal_data ?? {})
|
|
53
58
|
});
|
|
59
|
+
this.maybePruneDatabase();
|
|
54
60
|
}
|
|
55
61
|
async getAllQueries(pagination) {
|
|
56
62
|
return await this.paginate("query" /* QUERY */, pagination);
|
|
@@ -126,6 +132,36 @@ var BetterSqliteStore = class extends Store {
|
|
|
126
132
|
this.connection.exec(createIndex);
|
|
127
133
|
this.connection.exec(lensEntryIdIndex);
|
|
128
134
|
}
|
|
135
|
+
maybePruneDatabase() {
|
|
136
|
+
const maxGb = this.storeConfig?.dbMaxSizeGb;
|
|
137
|
+
const pruneGb = this.storeConfig?.dbPruneSizeGb;
|
|
138
|
+
if (!maxGb || !pruneGb) return;
|
|
139
|
+
const maxBytes = maxGb * BYTES_IN_GB;
|
|
140
|
+
const pruneBytes = pruneGb * BYTES_IN_GB;
|
|
141
|
+
if (maxBytes <= 0 || pruneBytes <= 0) return;
|
|
142
|
+
const targetBytes = Math.max(0, maxBytes - pruneBytes);
|
|
143
|
+
let usedBytes = this.getDatabaseUsedBytes();
|
|
144
|
+
if (usedBytes < maxBytes) return;
|
|
145
|
+
while (usedBytes > targetBytes) {
|
|
146
|
+
const deletedRows = this.deleteOldestEntries(PRUNE_BATCH_SIZE);
|
|
147
|
+
if (deletedRows === 0) break;
|
|
148
|
+
usedBytes = this.getDatabaseUsedBytes();
|
|
149
|
+
}
|
|
150
|
+
this.connection.exec("PRAGMA wal_checkpoint(TRUNCATE);");
|
|
151
|
+
}
|
|
152
|
+
getDatabaseUsedBytes() {
|
|
153
|
+
const pageSizeResult = this.connection.prepare("PRAGMA page_size;").get();
|
|
154
|
+
const pageCountResult = this.connection.prepare("PRAGMA page_count;").get();
|
|
155
|
+
const freelistCountResult = this.connection.prepare("PRAGMA freelist_count;").get();
|
|
156
|
+
const usedPages = pageCountResult.page_count - freelistCountResult.freelist_count;
|
|
157
|
+
return usedPages * pageSizeResult.page_size;
|
|
158
|
+
}
|
|
159
|
+
deleteOldestEntries(batchSize) {
|
|
160
|
+
const result = this.connection.prepare(
|
|
161
|
+
`DELETE FROM ${TABLE_NAME} WHERE id IN (SELECT id FROM ${TABLE_NAME} ORDER BY created_at ASC LIMIT ?)`
|
|
162
|
+
).run(batchSize);
|
|
163
|
+
return Number(result.changes ?? 0);
|
|
164
|
+
}
|
|
129
165
|
mapRow(row, includeFullData = true) {
|
|
130
166
|
let data = includeFullData ? JSON.parse(row.data) : {};
|
|
131
167
|
if (!includeFullData) {
|
package/dist/stores/index.cjs
CHANGED
|
@@ -30,12 +30,16 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/stores/index.ts
|
|
31
31
|
var stores_exports = {};
|
|
32
32
|
__export(stores_exports, {
|
|
33
|
-
BetterSqliteStore: () => BetterSqliteStore
|
|
33
|
+
BetterSqliteStore: () => BetterSqliteStore,
|
|
34
|
+
QueuedSqliteStore: () => QueuedSqliteStore
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(stores_exports);
|
|
36
37
|
|
|
37
38
|
// src/abstracts/store.ts
|
|
38
39
|
var Store = class {
|
|
40
|
+
storeConfig;
|
|
41
|
+
constructor(...args) {
|
|
42
|
+
}
|
|
39
43
|
getAllExceptions(_paginationParams) {
|
|
40
44
|
return this.defaultMinimalPaginate();
|
|
41
45
|
}
|
|
@@ -66,6 +70,8 @@ var import_crypto = require("crypto");
|
|
|
66
70
|
var import_libsql = __toESM(require("libsql"), 1);
|
|
67
71
|
var import_date = require("@lensjs/date");
|
|
68
72
|
var TABLE_NAME = "lens_entries";
|
|
73
|
+
var BYTES_IN_GB = 1024 * 1024 * 1024;
|
|
74
|
+
var PRUNE_BATCH_SIZE = 1e3;
|
|
69
75
|
var BetterSqliteStore = class extends Store {
|
|
70
76
|
connection;
|
|
71
77
|
async initialize() {
|
|
@@ -87,6 +93,7 @@ var BetterSqliteStore = class extends Store {
|
|
|
87
93
|
lens_entry_id: entry.requestId || null,
|
|
88
94
|
minimalData: this.stringifyData(entry.minimal_data ?? {})
|
|
89
95
|
});
|
|
96
|
+
this.maybePruneDatabase();
|
|
90
97
|
}
|
|
91
98
|
async getAllQueries(pagination) {
|
|
92
99
|
return await this.paginate("query" /* QUERY */, pagination);
|
|
@@ -162,6 +169,36 @@ var BetterSqliteStore = class extends Store {
|
|
|
162
169
|
this.connection.exec(createIndex);
|
|
163
170
|
this.connection.exec(lensEntryIdIndex);
|
|
164
171
|
}
|
|
172
|
+
maybePruneDatabase() {
|
|
173
|
+
const maxGb = this.storeConfig?.dbMaxSizeGb;
|
|
174
|
+
const pruneGb = this.storeConfig?.dbPruneSizeGb;
|
|
175
|
+
if (!maxGb || !pruneGb) return;
|
|
176
|
+
const maxBytes = maxGb * BYTES_IN_GB;
|
|
177
|
+
const pruneBytes = pruneGb * BYTES_IN_GB;
|
|
178
|
+
if (maxBytes <= 0 || pruneBytes <= 0) return;
|
|
179
|
+
const targetBytes = Math.max(0, maxBytes - pruneBytes);
|
|
180
|
+
let usedBytes = this.getDatabaseUsedBytes();
|
|
181
|
+
if (usedBytes < maxBytes) return;
|
|
182
|
+
while (usedBytes > targetBytes) {
|
|
183
|
+
const deletedRows = this.deleteOldestEntries(PRUNE_BATCH_SIZE);
|
|
184
|
+
if (deletedRows === 0) break;
|
|
185
|
+
usedBytes = this.getDatabaseUsedBytes();
|
|
186
|
+
}
|
|
187
|
+
this.connection.exec("PRAGMA wal_checkpoint(TRUNCATE);");
|
|
188
|
+
}
|
|
189
|
+
getDatabaseUsedBytes() {
|
|
190
|
+
const pageSizeResult = this.connection.prepare("PRAGMA page_size;").get();
|
|
191
|
+
const pageCountResult = this.connection.prepare("PRAGMA page_count;").get();
|
|
192
|
+
const freelistCountResult = this.connection.prepare("PRAGMA freelist_count;").get();
|
|
193
|
+
const usedPages = pageCountResult.page_count - freelistCountResult.freelist_count;
|
|
194
|
+
return usedPages * pageSizeResult.page_size;
|
|
195
|
+
}
|
|
196
|
+
deleteOldestEntries(batchSize) {
|
|
197
|
+
const result = this.connection.prepare(
|
|
198
|
+
`DELETE FROM ${TABLE_NAME} WHERE id IN (SELECT id FROM ${TABLE_NAME} ORDER BY created_at ASC LIMIT ?)`
|
|
199
|
+
).run(batchSize);
|
|
200
|
+
return Number(result.changes ?? 0);
|
|
201
|
+
}
|
|
165
202
|
mapRow(row, includeFullData = true) {
|
|
166
203
|
let data = includeFullData ? JSON.parse(row.data) : {};
|
|
167
204
|
if (!includeFullData) {
|
|
@@ -186,7 +223,97 @@ var BetterSqliteStore = class extends Store {
|
|
|
186
223
|
return `SELECT id, minimal_data, type, created_at, lens_entry_id ${includeFullData ? ",data" : ""}`;
|
|
187
224
|
}
|
|
188
225
|
};
|
|
226
|
+
|
|
227
|
+
// src/mixins/queued_store.ts
|
|
228
|
+
var import_denque = __toESM(require("denque"), 1);
|
|
229
|
+
function QueuedStore(Base) {
|
|
230
|
+
return class Queued extends Base {
|
|
231
|
+
queue;
|
|
232
|
+
processingInterval = null;
|
|
233
|
+
BATCH_SIZE;
|
|
234
|
+
PROCESS_INTERVAL_MS;
|
|
235
|
+
WARN_THRESHOLD;
|
|
236
|
+
PREALLOCATE;
|
|
237
|
+
constructor(...args) {
|
|
238
|
+
super(...args);
|
|
239
|
+
const config = args[0] || {};
|
|
240
|
+
this.storeConfig = config;
|
|
241
|
+
this.BATCH_SIZE = config.batchSize ?? 100;
|
|
242
|
+
this.PROCESS_INTERVAL_MS = config.processIntervalMs ?? 100;
|
|
243
|
+
this.WARN_THRESHOLD = config.warnThreshold ?? 1e5;
|
|
244
|
+
this.PREALLOCATE = config.preallocate ?? true;
|
|
245
|
+
this.queue = this.PREALLOCATE ? new import_denque.default([], { capacity: this.WARN_THRESHOLD * 2 }) : new import_denque.default();
|
|
246
|
+
}
|
|
247
|
+
async initialize() {
|
|
248
|
+
if (super["initialize"]) {
|
|
249
|
+
await super["initialize"].call(this);
|
|
250
|
+
}
|
|
251
|
+
this.startProcessingQueue();
|
|
252
|
+
process.on("SIGINT", () => this.shutdown());
|
|
253
|
+
process.on("SIGTERM", () => this.shutdown());
|
|
254
|
+
}
|
|
255
|
+
async truncate() {
|
|
256
|
+
this.queue.clear();
|
|
257
|
+
if (super["truncate"]) {
|
|
258
|
+
await super["truncate"].call(this);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async save(entry) {
|
|
262
|
+
this.queue.push(entry);
|
|
263
|
+
if (this.queue.length > this.WARN_THRESHOLD) {
|
|
264
|
+
console.warn(`\u26A0\uFE0F LensJs Queue size very large: ${this.queue.length}`);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
startProcessingQueue() {
|
|
268
|
+
if (this.processingInterval) clearInterval(this.processingInterval);
|
|
269
|
+
this.processingInterval = setInterval(
|
|
270
|
+
() => this.processQueue(),
|
|
271
|
+
this.PROCESS_INTERVAL_MS
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
async processQueue() {
|
|
275
|
+
if (this.queue.isEmpty()) return;
|
|
276
|
+
const batchSize = Math.min(
|
|
277
|
+
this.BATCH_SIZE,
|
|
278
|
+
Math.max(10, Math.floor(this.queue.length / 10))
|
|
279
|
+
);
|
|
280
|
+
const entriesToProcess = this.queue.remove(0, batchSize);
|
|
281
|
+
if (!entriesToProcess.length) return;
|
|
282
|
+
for (const entry of entriesToProcess) {
|
|
283
|
+
super["save"]?.call(this, entry).catch((error) => {
|
|
284
|
+
console.error("Error saving queued entry:", error);
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
async stopProcessingQueue() {
|
|
289
|
+
if (this.processingInterval) {
|
|
290
|
+
clearInterval(this.processingInterval);
|
|
291
|
+
this.processingInterval = null;
|
|
292
|
+
}
|
|
293
|
+
if (!this.queue.isEmpty()) {
|
|
294
|
+
await this.processQueue();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async shutdown() {
|
|
298
|
+
await this.stopProcessingQueue();
|
|
299
|
+
process.exit(0);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// src/utils/compose.ts
|
|
305
|
+
function compose(superclass, ...mixins) {
|
|
306
|
+
return mixins.reduce((c, mixin) => mixin(c), superclass);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// src/stores/queued_sqlite.ts
|
|
310
|
+
var QueuedSqliteStore = class extends compose(
|
|
311
|
+
BetterSqliteStore,
|
|
312
|
+
QueuedStore
|
|
313
|
+
) {
|
|
314
|
+
};
|
|
189
315
|
// Annotate the CommonJS export names for ESM import in node:
|
|
190
316
|
0 && (module.exports = {
|
|
191
|
-
BetterSqliteStore
|
|
317
|
+
BetterSqliteStore,
|
|
318
|
+
QueuedSqliteStore
|
|
192
319
|
});
|
package/dist/stores/index.d.cts
CHANGED
package/dist/stores/index.d.ts
CHANGED
package/dist/stores/index.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
// src/abstracts/store.ts
|
|
2
2
|
var Store = class {
|
|
3
|
+
storeConfig;
|
|
4
|
+
constructor(...args) {
|
|
5
|
+
}
|
|
3
6
|
getAllExceptions(_paginationParams) {
|
|
4
7
|
return this.defaultMinimalPaginate();
|
|
5
8
|
}
|
|
@@ -30,6 +33,8 @@ import { randomUUID } from "crypto";
|
|
|
30
33
|
import Database from "libsql";
|
|
31
34
|
import { nowISO } from "@lensjs/date";
|
|
32
35
|
var TABLE_NAME = "lens_entries";
|
|
36
|
+
var BYTES_IN_GB = 1024 * 1024 * 1024;
|
|
37
|
+
var PRUNE_BATCH_SIZE = 1e3;
|
|
33
38
|
var BetterSqliteStore = class extends Store {
|
|
34
39
|
connection;
|
|
35
40
|
async initialize() {
|
|
@@ -51,6 +56,7 @@ var BetterSqliteStore = class extends Store {
|
|
|
51
56
|
lens_entry_id: entry.requestId || null,
|
|
52
57
|
minimalData: this.stringifyData(entry.minimal_data ?? {})
|
|
53
58
|
});
|
|
59
|
+
this.maybePruneDatabase();
|
|
54
60
|
}
|
|
55
61
|
async getAllQueries(pagination) {
|
|
56
62
|
return await this.paginate("query" /* QUERY */, pagination);
|
|
@@ -126,6 +132,36 @@ var BetterSqliteStore = class extends Store {
|
|
|
126
132
|
this.connection.exec(createIndex);
|
|
127
133
|
this.connection.exec(lensEntryIdIndex);
|
|
128
134
|
}
|
|
135
|
+
maybePruneDatabase() {
|
|
136
|
+
const maxGb = this.storeConfig?.dbMaxSizeGb;
|
|
137
|
+
const pruneGb = this.storeConfig?.dbPruneSizeGb;
|
|
138
|
+
if (!maxGb || !pruneGb) return;
|
|
139
|
+
const maxBytes = maxGb * BYTES_IN_GB;
|
|
140
|
+
const pruneBytes = pruneGb * BYTES_IN_GB;
|
|
141
|
+
if (maxBytes <= 0 || pruneBytes <= 0) return;
|
|
142
|
+
const targetBytes = Math.max(0, maxBytes - pruneBytes);
|
|
143
|
+
let usedBytes = this.getDatabaseUsedBytes();
|
|
144
|
+
if (usedBytes < maxBytes) return;
|
|
145
|
+
while (usedBytes > targetBytes) {
|
|
146
|
+
const deletedRows = this.deleteOldestEntries(PRUNE_BATCH_SIZE);
|
|
147
|
+
if (deletedRows === 0) break;
|
|
148
|
+
usedBytes = this.getDatabaseUsedBytes();
|
|
149
|
+
}
|
|
150
|
+
this.connection.exec("PRAGMA wal_checkpoint(TRUNCATE);");
|
|
151
|
+
}
|
|
152
|
+
getDatabaseUsedBytes() {
|
|
153
|
+
const pageSizeResult = this.connection.prepare("PRAGMA page_size;").get();
|
|
154
|
+
const pageCountResult = this.connection.prepare("PRAGMA page_count;").get();
|
|
155
|
+
const freelistCountResult = this.connection.prepare("PRAGMA freelist_count;").get();
|
|
156
|
+
const usedPages = pageCountResult.page_count - freelistCountResult.freelist_count;
|
|
157
|
+
return usedPages * pageSizeResult.page_size;
|
|
158
|
+
}
|
|
159
|
+
deleteOldestEntries(batchSize) {
|
|
160
|
+
const result = this.connection.prepare(
|
|
161
|
+
`DELETE FROM ${TABLE_NAME} WHERE id IN (SELECT id FROM ${TABLE_NAME} ORDER BY created_at ASC LIMIT ?)`
|
|
162
|
+
).run(batchSize);
|
|
163
|
+
return Number(result.changes ?? 0);
|
|
164
|
+
}
|
|
129
165
|
mapRow(row, includeFullData = true) {
|
|
130
166
|
let data = includeFullData ? JSON.parse(row.data) : {};
|
|
131
167
|
if (!includeFullData) {
|
|
@@ -150,6 +186,96 @@ var BetterSqliteStore = class extends Store {
|
|
|
150
186
|
return `SELECT id, minimal_data, type, created_at, lens_entry_id ${includeFullData ? ",data" : ""}`;
|
|
151
187
|
}
|
|
152
188
|
};
|
|
189
|
+
|
|
190
|
+
// src/mixins/queued_store.ts
|
|
191
|
+
import Denque from "denque";
|
|
192
|
+
function QueuedStore(Base) {
|
|
193
|
+
return class Queued extends Base {
|
|
194
|
+
queue;
|
|
195
|
+
processingInterval = null;
|
|
196
|
+
BATCH_SIZE;
|
|
197
|
+
PROCESS_INTERVAL_MS;
|
|
198
|
+
WARN_THRESHOLD;
|
|
199
|
+
PREALLOCATE;
|
|
200
|
+
constructor(...args) {
|
|
201
|
+
super(...args);
|
|
202
|
+
const config = args[0] || {};
|
|
203
|
+
this.storeConfig = config;
|
|
204
|
+
this.BATCH_SIZE = config.batchSize ?? 100;
|
|
205
|
+
this.PROCESS_INTERVAL_MS = config.processIntervalMs ?? 100;
|
|
206
|
+
this.WARN_THRESHOLD = config.warnThreshold ?? 1e5;
|
|
207
|
+
this.PREALLOCATE = config.preallocate ?? true;
|
|
208
|
+
this.queue = this.PREALLOCATE ? new Denque([], { capacity: this.WARN_THRESHOLD * 2 }) : new Denque();
|
|
209
|
+
}
|
|
210
|
+
async initialize() {
|
|
211
|
+
if (super["initialize"]) {
|
|
212
|
+
await super["initialize"].call(this);
|
|
213
|
+
}
|
|
214
|
+
this.startProcessingQueue();
|
|
215
|
+
process.on("SIGINT", () => this.shutdown());
|
|
216
|
+
process.on("SIGTERM", () => this.shutdown());
|
|
217
|
+
}
|
|
218
|
+
async truncate() {
|
|
219
|
+
this.queue.clear();
|
|
220
|
+
if (super["truncate"]) {
|
|
221
|
+
await super["truncate"].call(this);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
async save(entry) {
|
|
225
|
+
this.queue.push(entry);
|
|
226
|
+
if (this.queue.length > this.WARN_THRESHOLD) {
|
|
227
|
+
console.warn(`\u26A0\uFE0F LensJs Queue size very large: ${this.queue.length}`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
startProcessingQueue() {
|
|
231
|
+
if (this.processingInterval) clearInterval(this.processingInterval);
|
|
232
|
+
this.processingInterval = setInterval(
|
|
233
|
+
() => this.processQueue(),
|
|
234
|
+
this.PROCESS_INTERVAL_MS
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
async processQueue() {
|
|
238
|
+
if (this.queue.isEmpty()) return;
|
|
239
|
+
const batchSize = Math.min(
|
|
240
|
+
this.BATCH_SIZE,
|
|
241
|
+
Math.max(10, Math.floor(this.queue.length / 10))
|
|
242
|
+
);
|
|
243
|
+
const entriesToProcess = this.queue.remove(0, batchSize);
|
|
244
|
+
if (!entriesToProcess.length) return;
|
|
245
|
+
for (const entry of entriesToProcess) {
|
|
246
|
+
super["save"]?.call(this, entry).catch((error) => {
|
|
247
|
+
console.error("Error saving queued entry:", error);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async stopProcessingQueue() {
|
|
252
|
+
if (this.processingInterval) {
|
|
253
|
+
clearInterval(this.processingInterval);
|
|
254
|
+
this.processingInterval = null;
|
|
255
|
+
}
|
|
256
|
+
if (!this.queue.isEmpty()) {
|
|
257
|
+
await this.processQueue();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
async shutdown() {
|
|
261
|
+
await this.stopProcessingQueue();
|
|
262
|
+
process.exit(0);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/utils/compose.ts
|
|
268
|
+
function compose(superclass, ...mixins) {
|
|
269
|
+
return mixins.reduce((c, mixin) => mixin(c), superclass);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/stores/queued_sqlite.ts
|
|
273
|
+
var QueuedSqliteStore = class extends compose(
|
|
274
|
+
BetterSqliteStore,
|
|
275
|
+
QueuedStore
|
|
276
|
+
) {
|
|
277
|
+
};
|
|
153
278
|
export {
|
|
154
|
-
BetterSqliteStore
|
|
279
|
+
BetterSqliteStore,
|
|
280
|
+
QueuedSqliteStore
|
|
155
281
|
};
|