getaimeter 0.1.2 → 0.1.4
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 +1 -1
- package/watcher.js +32 -4
package/package.json
CHANGED
package/watcher.js
CHANGED
|
@@ -138,6 +138,7 @@ async function reportEvents(events) {
|
|
|
138
138
|
// ---------------------------------------------------------------------------
|
|
139
139
|
|
|
140
140
|
const _debounceTimers = new Map();
|
|
141
|
+
const _processing = new Set();
|
|
141
142
|
|
|
142
143
|
function handleFileChange(filePath) {
|
|
143
144
|
// Only care about .jsonl files
|
|
@@ -146,12 +147,17 @@ function handleFileChange(filePath) {
|
|
|
146
147
|
// Normalize path for consistent debounce key (Windows fires with mixed separators/casing)
|
|
147
148
|
const normalizedKey = path.resolve(filePath).toLowerCase();
|
|
148
149
|
|
|
149
|
-
//
|
|
150
|
+
// Skip if already being processed
|
|
151
|
+
if (_processing.has(normalizedKey)) return;
|
|
152
|
+
|
|
153
|
+
// Debounce: wait 2000ms after last change before processing
|
|
150
154
|
const existing = _debounceTimers.get(normalizedKey);
|
|
151
155
|
if (existing) clearTimeout(existing);
|
|
152
156
|
|
|
153
157
|
_debounceTimers.set(normalizedKey, setTimeout(async () => {
|
|
154
158
|
_debounceTimers.delete(normalizedKey);
|
|
159
|
+
if (_processing.has(normalizedKey)) return;
|
|
160
|
+
_processing.add(normalizedKey);
|
|
155
161
|
try {
|
|
156
162
|
const events = extractNewUsage(filePath);
|
|
157
163
|
if (events.length > 0) {
|
|
@@ -160,8 +166,10 @@ function handleFileChange(filePath) {
|
|
|
160
166
|
}
|
|
161
167
|
} catch (err) {
|
|
162
168
|
logError(`Processing ${filePath}:`, err.message);
|
|
169
|
+
} finally {
|
|
170
|
+
_processing.delete(normalizedKey);
|
|
163
171
|
}
|
|
164
|
-
},
|
|
172
|
+
}, 2000));
|
|
165
173
|
}
|
|
166
174
|
|
|
167
175
|
/**
|
|
@@ -240,7 +248,7 @@ function startWatching() {
|
|
|
240
248
|
}
|
|
241
249
|
saveState();
|
|
242
250
|
|
|
243
|
-
// Set up fs.watch on each path
|
|
251
|
+
// Set up fs.watch on each path (works well on macOS/Linux)
|
|
244
252
|
const watchers = [];
|
|
245
253
|
for (const watchPath of watchPaths) {
|
|
246
254
|
try {
|
|
@@ -255,18 +263,38 @@ function startWatching() {
|
|
|
255
263
|
});
|
|
256
264
|
|
|
257
265
|
watchers.push(w);
|
|
258
|
-
log('Watching:', watchPath);
|
|
266
|
+
log('Watching (fs.watch):', watchPath);
|
|
259
267
|
} catch (err) {
|
|
260
268
|
logError(`Could not watch ${watchPath}:`, err.message);
|
|
261
269
|
}
|
|
262
270
|
}
|
|
263
271
|
|
|
272
|
+
// Polling fallback — fs.watch is unreliable on Windows for deeply nested dirs.
|
|
273
|
+
// Every 5 seconds, scan all known JSONL files for size changes.
|
|
274
|
+
const POLL_INTERVAL = 5_000;
|
|
275
|
+
const pollInterval = setInterval(() => {
|
|
276
|
+
for (const watchPath of watchPaths) {
|
|
277
|
+
const files = findJsonlFiles(watchPath);
|
|
278
|
+
for (const file of files) {
|
|
279
|
+
try {
|
|
280
|
+
const currentSize = fs.statSync(file).size;
|
|
281
|
+
const lastOffset = getOffset(file);
|
|
282
|
+
if (currentSize > lastOffset) {
|
|
283
|
+
handleFileChange(file);
|
|
284
|
+
}
|
|
285
|
+
} catch {}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}, POLL_INTERVAL);
|
|
289
|
+
log(`Polling every ${POLL_INTERVAL / 1000}s as fallback`);
|
|
290
|
+
|
|
264
291
|
// Periodic state save
|
|
265
292
|
const saveInterval = setInterval(() => saveState(), 30_000);
|
|
266
293
|
|
|
267
294
|
// Return cleanup
|
|
268
295
|
return () => {
|
|
269
296
|
clearInterval(saveInterval);
|
|
297
|
+
clearInterval(pollInterval);
|
|
270
298
|
for (const w of watchers) w.close();
|
|
271
299
|
for (const t of _debounceTimers.values()) clearTimeout(t);
|
|
272
300
|
saveState();
|