Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | 25x 25x 25x 25x 25x 4x 3x 3x 1x 24x 24x 24x 24x 6x 6x 4x 4x 4x 4x 5x 5x 25x 28x 24x 28x 25x | /**
* Translation miss-queue (SHY-0072): append-only JSONL of (text, target)
* pairs the provider chain could not translate. Deduplicated on append
* (same text+target queues once, surviving restarts via hydrate-on-boot).
* Claude drains this via routine PRs that commit translations into the
* cache SEED (the "fallback to claude" — build-time, $0).
*
* Length surfaces in GET /api/system/health as `translationQueueLength`
* (computed lazily from the file so the reader never races the writer).
*/
const fs = require('node:fs');
const path = require('node:path');
const os = require('node:os');
// NUL separator: cannot appear in either field, so user-controlled text
// can never collide two distinct (text, target) pairs in the dedupe set.
const SEP = '\u0000';
// Under Jest, an un-overridden queue path falls back to a per-process
// tmpdir (same rationale as translation-cache's test default).
let testDefaultDir = null;
function defaultQueuePath() {
if (process.env.NODE_ENV === 'test') {
Eif (!testDefaultDir) testDefaultDir = fs.mkdtempSync(path.join(os.tmpdir(), 'tqueue-default-'));
return path.join(testDefaultDir, 'translation-miss-queue.jsonl');
}
return path.join(__dirname, '..', '..', 'data', 'translation-miss-queue.jsonl');
}
function createMissQueue({ queuePath = defaultQueuePath() } = {}) {
const seen = new Set();
try {
Iif (fs.existsSync(queuePath)) {
for (const line of fs.readFileSync(queuePath, 'utf-8').split('\n')) {
if (!line.trim()) continue;
try {
const e = JSON.parse(line);
seen.add(`${e.text}${SEP}${e.target}`);
} catch {
// A corrupt line never blocks queueing; backfill tooling skips it too.
}
}
}
} catch {
// Unreadable queue file = start with an empty dedupe set; appends recreate it.
}
return {
/** @returns {boolean} true if appended, false if deduplicated away */
enqueue(text, target, reason) {
const k = `${text}${SEP}${target}`;
if (seen.has(k)) return false;
seen.add(k);
fs.mkdirSync(path.dirname(queuePath), { recursive: true });
fs.appendFileSync(
queuePath,
`${JSON.stringify({ text, target, ts: new Date().toISOString(), reason })}\n`,
);
return true;
},
/** Lazily counted line length (admin backlog signal for /system/health). */
length() {
try {
Eif (!fs.existsSync(queuePath)) return 0;
return fs
.readFileSync(queuePath, 'utf-8')
.split('\n')
.filter((l) => l.trim()).length;
} catch {
return 0;
}
},
};
}
let defaultInstance = null;
/** Lazy singleton bound to env-overridable path (tests reset via resetModules). */
function getDefaultMissQueue() {
if (!defaultInstance) {
defaultInstance = createMissQueue({
queuePath: process.env.TRANSLATION_MISS_QUEUE_PATH || defaultQueuePath(),
});
}
return defaultInstance;
}
module.exports = { createMissQueue, getDefaultMissQueue };
|