muaddib-scanner 2.11.95 → 2.11.96
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/package.json
CHANGED
package/src/monitor/spill.js
CHANGED
|
@@ -83,9 +83,24 @@ function _writeEntries(file, entries) {
|
|
|
83
83
|
fs.renameSync(tmp, file);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
// Conservative upper bound on a spilled line's byte size (the SPILL_FIELDS
|
|
87
|
+
// record + ts + newline run ~150-250 bytes). Used for the O(1) stat-gated
|
|
88
|
+
// compaction trigger below — overestimating only makes compaction fire a bit
|
|
89
|
+
// late, never early, so the file ceiling stays ~MUADDIB_SPILL_MAX.
|
|
90
|
+
const SPILL_LINE_BYTES_EST = 256;
|
|
91
|
+
|
|
86
92
|
/**
|
|
87
93
|
* Append evicted queue items to the backlog. Never throws; on write failure the
|
|
88
94
|
* caller's fallback is the pre-spill behavior (drop, ledgered).
|
|
95
|
+
*
|
|
96
|
+
* HOT PATH — runs INSIDE the EMERGENCY memory handler (evictFromScanQueueBulk),
|
|
97
|
+
* so it MUST be append-only and allocation-free beyond the write buffer. The
|
|
98
|
+
* 2026-06-11 freeze was caused by calling _compactBacklog (which reads + parses
|
|
99
|
+
* the WHOLE backlog) on every spill: a large allocation during a reclaim stall
|
|
100
|
+
* that wedged the handler before it could free RSS. Compaction now fires ONLY
|
|
101
|
+
* when a cheap statSync shows the file is genuinely near the cap (normally
|
|
102
|
+
* never during an EMERGENCY — the backlog is far below the byte budget there),
|
|
103
|
+
* and the calm-time drain also keeps it bounded.
|
|
89
104
|
* @param {Array<object>} items evicted scan-queue items
|
|
90
105
|
* @returns {number} how many items were actually persisted
|
|
91
106
|
*/
|
|
@@ -107,7 +122,11 @@ function spillItems(items) {
|
|
|
107
122
|
written++;
|
|
108
123
|
}
|
|
109
124
|
if (buf) fs.appendFileSync(file, buf, 'utf8');
|
|
110
|
-
|
|
125
|
+
// O(1) stat-gated compaction: only read+rewrite the file when it is actually
|
|
126
|
+
// near the cap. NO whole-file read on the normal EMERGENCY spill path.
|
|
127
|
+
let size = 0;
|
|
128
|
+
try { size = fs.statSync(file).size; } catch { /* fresh file */ }
|
|
129
|
+
if (size > _maxEntries() * SPILL_LINE_BYTES_EST) _compactBacklog(file);
|
|
111
130
|
} catch {
|
|
112
131
|
return 0; // degrade to drop-with-ledger at the call site
|
|
113
132
|
}
|