@threadbase-sh/streamer 1.36.2 → 1.36.3
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/cli.cjs +31 -8
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +31 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +31 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6899,6 +6899,10 @@ var StreamerServer = class {
|
|
|
6899
6899
|
// Set by onConversationChanged while a scan is in-flight; getScanner() does
|
|
6900
6900
|
// a single rescan after the current one completes instead of restarting it.
|
|
6901
6901
|
scannerStale = false;
|
|
6902
|
+
// Single-flight guard for the background disk reconcile: a burst of list
|
|
6903
|
+
// polls during active session writes shares one rescan instead of queueing
|
|
6904
|
+
// a full rescan per request.
|
|
6905
|
+
conversationReconcileInFlight = null;
|
|
6902
6906
|
// Single-flight + TTL guard around scanner.refreshFile (see refreshFileGuarded).
|
|
6903
6907
|
// A live file's mtime is always newer than the snapshot, so an unguarded
|
|
6904
6908
|
// refresh fires on every request and re-parses the whole file from byte 0.
|
|
@@ -7916,9 +7920,9 @@ var StreamerServer = class {
|
|
|
7916
7920
|
* the automatic freshness path when the directory watcher marked the scanner
|
|
7917
7921
|
* stale or shouldRefreshProjectsFromHdd detected disk drift.
|
|
7918
7922
|
*/
|
|
7919
|
-
async reconcileConversationsCacheFromDisk() {
|
|
7923
|
+
async reconcileConversationsCacheFromDisk(onProgress) {
|
|
7920
7924
|
if (!this.cache) return;
|
|
7921
|
-
const scanner = await this.rescanForRefresh();
|
|
7925
|
+
const scanner = await this.rescanForRefresh(onProgress);
|
|
7922
7926
|
const metas = [...scanner.getMetadataCache().values()];
|
|
7923
7927
|
try {
|
|
7924
7928
|
this.cache.upsertFromScannerMeta(metas);
|
|
@@ -7946,6 +7950,18 @@ var StreamerServer = class {
|
|
|
7946
7950
|
);
|
|
7947
7951
|
}
|
|
7948
7952
|
}
|
|
7953
|
+
// Reconcile the cache from disk without blocking the caller. Single-flighted
|
|
7954
|
+
// so a burst of list polls during active session writes shares one rescan
|
|
7955
|
+
// rather than queueing a full rescan each; tracked so close() awaits the
|
|
7956
|
+
// in-flight cache write before shutting the DB.
|
|
7957
|
+
startBackgroundConversationReconcile() {
|
|
7958
|
+
if (this.conversationReconcileInFlight) return;
|
|
7959
|
+
const task = this.reconcileConversationsCacheFromDisk().finally(() => {
|
|
7960
|
+
this.conversationReconcileInFlight = null;
|
|
7961
|
+
});
|
|
7962
|
+
this.conversationReconcileInFlight = task;
|
|
7963
|
+
this.trackCacheWrite(task);
|
|
7964
|
+
}
|
|
7949
7965
|
shouldAutoReconcileConversationList() {
|
|
7950
7966
|
if (!this.cache) return false;
|
|
7951
7967
|
if (this.scannerStale) return true;
|
|
@@ -7963,13 +7979,19 @@ var StreamerServer = class {
|
|
|
7963
7979
|
const providerFilter = url.searchParams.get("provider") ?? void 0;
|
|
7964
7980
|
const bustCache = url.searchParams.get("refresh") === "1";
|
|
7965
7981
|
if (this.cache && (bustCache || this.shouldAutoReconcileConversationList())) {
|
|
7966
|
-
|
|
7982
|
+
const canServeStale = !bustCache && this.cache.listConversations({ limit: 0, offset: 0 }).total > 0;
|
|
7983
|
+
if (canServeStale) {
|
|
7984
|
+
this.startBackgroundConversationReconcile();
|
|
7985
|
+
} else {
|
|
7986
|
+
const shouldEmitProgress = createScanProgressThrottle();
|
|
7967
7987
|
await this.withWarmup(
|
|
7968
7988
|
"conversation_refresh",
|
|
7969
|
-
() => this.reconcileConversationsCacheFromDisk()
|
|
7989
|
+
() => this.reconcileConversationsCacheFromDisk((scanned, total2) => {
|
|
7990
|
+
if (shouldEmitProgress(scanned, total2)) {
|
|
7991
|
+
this.wsHub.broadcast({ type: "scan_progress", scanned, total: total2 });
|
|
7992
|
+
}
|
|
7993
|
+
})
|
|
7970
7994
|
);
|
|
7971
|
-
} else {
|
|
7972
|
-
await this.reconcileConversationsCacheFromDisk();
|
|
7973
7995
|
}
|
|
7974
7996
|
}
|
|
7975
7997
|
if (this.cache) {
|
|
@@ -8205,7 +8227,7 @@ var StreamerServer = class {
|
|
|
8205
8227
|
// getFreshScanner() this does NOT discard the warm scanner. scannerReady is
|
|
8206
8228
|
// only ever reassigned to a live scan promise (never nulled mid-scan), so the
|
|
8207
8229
|
// getScanner() anti-infinite-loop guard is preserved.
|
|
8208
|
-
async rescanForRefresh() {
|
|
8230
|
+
async rescanForRefresh(onProgress) {
|
|
8209
8231
|
if (this.scannerReady) await this.scannerReady;
|
|
8210
8232
|
this.scannerStale = false;
|
|
8211
8233
|
if (!this.scanner) {
|
|
@@ -8216,7 +8238,8 @@ var StreamerServer = class {
|
|
|
8216
8238
|
this.scannerReady = scanner.scan({
|
|
8217
8239
|
...this.scanProfiles ? { profiles: this.scanProfiles } : {},
|
|
8218
8240
|
...this.codexScanOpts(),
|
|
8219
|
-
fullRescan: true
|
|
8241
|
+
fullRescan: true,
|
|
8242
|
+
...onProgress ? { onProgress } : {}
|
|
8220
8243
|
});
|
|
8221
8244
|
await this.scannerReady;
|
|
8222
8245
|
return scanner;
|