getaimeter 0.1.3 → 0.1.5
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 +35 -61
package/package.json
CHANGED
package/watcher.js
CHANGED
|
@@ -137,31 +137,20 @@ async function reportEvents(events) {
|
|
|
137
137
|
// File watcher
|
|
138
138
|
// ---------------------------------------------------------------------------
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const existing = _debounceTimers.get(normalizedKey);
|
|
151
|
-
if (existing) clearTimeout(existing);
|
|
152
|
-
|
|
153
|
-
_debounceTimers.set(normalizedKey, setTimeout(async () => {
|
|
154
|
-
_debounceTimers.delete(normalizedKey);
|
|
155
|
-
try {
|
|
156
|
-
const events = extractNewUsage(filePath);
|
|
157
|
-
if (events.length > 0) {
|
|
158
|
-
await reportEvents(events);
|
|
159
|
-
saveState();
|
|
160
|
-
}
|
|
161
|
-
} catch (err) {
|
|
162
|
-
logError(`Processing ${filePath}:`, err.message);
|
|
140
|
+
/**
|
|
141
|
+
* Process a single file: extract new usage and report it.
|
|
142
|
+
* Called only from the poll loop — single-threaded, no races.
|
|
143
|
+
*/
|
|
144
|
+
async function processFile(filePath) {
|
|
145
|
+
try {
|
|
146
|
+
const events = extractNewUsage(filePath);
|
|
147
|
+
if (events.length > 0) {
|
|
148
|
+
await reportEvents(events);
|
|
149
|
+
saveState();
|
|
163
150
|
}
|
|
164
|
-
}
|
|
151
|
+
} catch (err) {
|
|
152
|
+
logError(`Processing ${filePath}:`, err.message);
|
|
153
|
+
}
|
|
165
154
|
}
|
|
166
155
|
|
|
167
156
|
/**
|
|
@@ -240,45 +229,32 @@ function startWatching() {
|
|
|
240
229
|
}
|
|
241
230
|
saveState();
|
|
242
231
|
|
|
243
|
-
//
|
|
244
|
-
|
|
245
|
-
for (const watchPath of watchPaths) {
|
|
246
|
-
try {
|
|
247
|
-
const w = fs.watch(watchPath, { recursive: true }, (eventType, filename) => {
|
|
248
|
-
if (!filename) return;
|
|
249
|
-
const fullPath = path.join(watchPath, filename);
|
|
250
|
-
handleFileChange(fullPath);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
w.on('error', (err) => {
|
|
254
|
-
logError(`Watcher error on ${watchPath}:`, err.message);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
watchers.push(w);
|
|
258
|
-
log('Watching (fs.watch):', watchPath);
|
|
259
|
-
} catch (err) {
|
|
260
|
-
logError(`Could not watch ${watchPath}:`, err.message);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Polling fallback — fs.watch is unreliable on Windows for deeply nested dirs.
|
|
265
|
-
// Every 5 seconds, scan all known JSONL files for size changes.
|
|
232
|
+
// Poll every 5 seconds — simple, reliable, no race conditions.
|
|
233
|
+
// fs.watch is unreliable on Windows for deeply nested dirs and fires duplicates.
|
|
266
234
|
const POLL_INTERVAL = 5_000;
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
235
|
+
let polling = false;
|
|
236
|
+
|
|
237
|
+
const pollInterval = setInterval(async () => {
|
|
238
|
+
if (polling) return; // skip if previous poll still running
|
|
239
|
+
polling = true;
|
|
240
|
+
try {
|
|
241
|
+
for (const watchPath of watchPaths) {
|
|
242
|
+
const files = findJsonlFiles(watchPath);
|
|
243
|
+
for (const file of files) {
|
|
244
|
+
try {
|
|
245
|
+
const currentSize = fs.statSync(file).size;
|
|
246
|
+
const lastOffset = getOffset(file);
|
|
247
|
+
if (currentSize > lastOffset) {
|
|
248
|
+
await processFile(file);
|
|
249
|
+
}
|
|
250
|
+
} catch {}
|
|
251
|
+
}
|
|
278
252
|
}
|
|
253
|
+
} finally {
|
|
254
|
+
polling = false;
|
|
279
255
|
}
|
|
280
256
|
}, POLL_INTERVAL);
|
|
281
|
-
log(`Polling every ${POLL_INTERVAL / 1000}s
|
|
257
|
+
log(`Polling every ${POLL_INTERVAL / 1000}s`);
|
|
282
258
|
|
|
283
259
|
// Periodic state save
|
|
284
260
|
const saveInterval = setInterval(() => saveState(), 30_000);
|
|
@@ -287,8 +263,6 @@ function startWatching() {
|
|
|
287
263
|
return () => {
|
|
288
264
|
clearInterval(saveInterval);
|
|
289
265
|
clearInterval(pollInterval);
|
|
290
|
-
for (const w of watchers) w.close();
|
|
291
|
-
for (const t of _debounceTimers.values()) clearTimeout(t);
|
|
292
266
|
saveState();
|
|
293
267
|
log('Watcher stopped.');
|
|
294
268
|
};
|