← back to Mfr Review Viewer Corruption
yoloforever c1 (Cody fix): single-flight lock in enrich-suggestions — concurrent rebuild-triggered runs can't race + corrupt queue.jsonl
d32eae4518a6a8a2f4d57827d5b1fe4698d1a4f8 · 2026-08-28 00:45:04 -0700 · Steve Abrams
Files touched
M scripts/enrich-suggestions.mjs
Diff
commit d32eae4518a6a8a2f4d57827d5b1fe4698d1a4f8
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Aug 28 00:45:04 2026 -0700
yoloforever c1 (Cody fix): single-flight lock in enrich-suggestions — concurrent rebuild-triggered runs can't race + corrupt queue.jsonl
---
scripts/enrich-suggestions.mjs | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/scripts/enrich-suggestions.mjs b/scripts/enrich-suggestions.mjs
index fa59795..d446250 100644
--- a/scripts/enrich-suggestions.mjs
+++ b/scripts/enrich-suggestions.mjs
@@ -10,12 +10,28 @@
// node scripts/enrich-suggestions.mjs --limit 50 # sample
// node scripts/enrich-suggestions.mjs --force # re-enrich even filled rows
-import { readFileSync, writeFileSync, existsSync } from 'node:fs';
+import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
const __dir = dirname(fileURLToPath(import.meta.url));
const QUEUE = join(__dir, '..', 'data', 'queue.jsonl');
+
+// ---- SINGLE-FLIGHT LOCK (Cody, cycle 1): two enrichers writing queue.jsonl at once
+// (e.g. ↻ Rebuild clicked twice) would race on the full-file rewrite and lose updates.
+// Take a lock; a stale lock (>2h, a crashed run) is reclaimed. Released on exit.
+const LOCK = join(__dir, '..', 'data', '.enrich.lock');
+if (existsSync(LOCK)) {
+ let age = Infinity;
+ try { age = Date.now() - JSON.parse(readFileSync(LOCK, 'utf8')).ts; } catch { age = Infinity; }
+ if (age < 2 * 60 * 60 * 1000) { console.log('enrich-suggestions: another run holds the lock — exiting (no double-write).'); process.exit(0); }
+ console.log('enrich-suggestions: reclaiming a stale lock (>2h).');
+}
+try { writeFileSync(LOCK, JSON.stringify({ pid: process.pid, ts: Date.now() })); } catch { /* best-effort */ }
+const releaseLock = () => { try { unlinkSync(LOCK); } catch { /* already gone */ } };
+process.on('exit', releaseLock);
+process.on('SIGTERM', () => { releaseLock(); process.exit(143); });
+process.on('SIGINT', () => { releaseLock(); process.exit(130); });
const LIMIT = (() => { const i = process.argv.indexOf('--limit'); return i > -1 ? parseInt(process.argv[i + 1], 10) : 0; })();
const FORCE = process.argv.includes('--force');
const PACE_MS = 350;
← 039cfdc yoloforever c1: wire /api/rebuild to auto-refill FileMaker s
·
back to Mfr Review Viewer Corruption
·
fix [110]: route sweep deletes/writes through Basic List of 1ba8310 →