(beforeBytes: number)
| 569 | private walHeal: Promise<{ healed: boolean; beforeBytes: number; afterBytes: number }> | null = null; |
| 570 | |
| 571 | private async runWalHeal(beforeBytes: number): Promise<{ healed: boolean; beforeBytes: number; afterBytes: number }> { |
| 572 | // A racing reader/writer (another session healing the same file, a query |
| 573 | // pool warming up) degrades a checkpoint pass to a busy no-op — retry a |
| 574 | // few times before leaving the rest to the next open. |
| 575 | for (let attempt = 0; attempt < 3; attempt++) { |
| 576 | if (attempt > 0) await new Promise((r) => setTimeout(r, 300)); |
| 577 | await this.checkpointWalPassive(); |
| 578 | await this.checkpointWalTruncate(); |
| 579 | if (this.getWalSizeBytes() <= WAL_HEAL_THRESHOLD_BYTES) break; |
| 580 | } |
| 581 | const afterBytes = this.getWalSizeBytes(); |
| 582 | if (process.env.CODEGRAPH_WAL_VALVE_DEBUG) { |
| 583 | console.error(`[wal-heal] oversized WAL at open: ${Math.round(beforeBytes / (1024 * 1024))}MB -> ${Math.round(afterBytes / (1024 * 1024))}MB`); |
| 584 | } |
| 585 | return { healed: afterBytes < beforeBytes, beforeBytes, afterBytes }; |
| 586 | } |
| 587 | |
| 588 | private async checkpointWal(mode: 'PASSIVE' | 'TRUNCATE'): Promise<{ busy: number; log: number; checkpointed: number } | null> { |
| 589 | if (!this.dbPath || this.dbPath === ':memory:') { |
no test coverage detected