* Atomically claim the queue for sending (rename). Concurrent processes * can't double-send; a crash mid-send leaves a claim file that * `recoverStaleClaims` merges back after an hour.
()
| 420 | * `recoverStaleClaims` merges back after an hour. |
| 421 | */ |
| 422 | private claimQueue(): { claimPath: string; lines: BufferLine[] } | null { |
| 423 | const claimPath = path.join(this.dir, `telemetry-queue.sending.${process.pid}.jsonl`); |
| 424 | try { |
| 425 | fs.renameSync(this.queuePath, claimPath); |
| 426 | } catch { |
| 427 | return null; // no queue, or another process just claimed it |
| 428 | } |
| 429 | const lines: BufferLine[] = []; |
| 430 | try { |
| 431 | for (const raw of fs.readFileSync(claimPath, 'utf8').split('\n')) { |
| 432 | if (!raw.trim()) continue; |
| 433 | try { |
| 434 | const parsed = JSON.parse(raw) as BufferLine; |
| 435 | if (parsed && typeof parsed === 'object' && parsed.v === SCHEMA_VERSION) lines.push(parsed); |
| 436 | } catch { |
| 437 | /* skip corrupt line */ |
| 438 | } |
| 439 | } |
| 440 | } catch { |
| 441 | /* unreadable claim — treat as empty; file removed by caller */ |
| 442 | } |
| 443 | return { claimPath, lines }; |
| 444 | } |
| 445 | |
| 446 | private recoverStaleClaims(): void { |
| 447 | try { |