* Writer-side backstop, called at a between-transactions boundary. Returns * null (no wait) while growth is under the hard cap; past it, returns a * promise that resolves only once a FULL backfill has landed — see the * header comment for why a single pass is not enough on a saturated disk.
()
| 172 | * header comment for why a single pass is not enough on a saturated disk. |
| 173 | */ |
| 174 | backpressure(): Promise<void> | null { |
| 175 | if (this.pause) return this.pause; |
| 176 | if (Date.now() < this.futileUntil) return null; // pinned reader — parking is churn, not progress |
| 177 | // Two independent triggers: |
| 178 | // - growth: un-backfilled BACKLOG past the hard cap (the original valve). |
| 179 | // - file size: a WAL can stay fully backfilled and still grow without |
| 180 | // bound — the writer only restarts at frame 0 if a commit finds no |
| 181 | // reader marks, which §7a.1's instrumented run showed never happens |
| 182 | // in practice (file marched 361→721MB through two COMPLETE |
| 183 | // backfills). Past the file cap, park and TRUNCATE at the barrier — |
| 184 | // the backfill part is instant when the backlog is already folded. |
| 185 | if (this.growthBytes() <= this.hardBytes && this.db.getWalSizeBytes() <= this.fileCapBytes) return null; |
| 186 | this.log(`backpressure: wal=${this.mb(this.db.getWalSizeBytes())} baseline=${this.mb(this.sizeAtLastFullBackfill)} — pausing writer for full backfill`); |
| 187 | const t0 = Date.now(); |
| 188 | this.pause = this.backfillFully().finally(() => { |
| 189 | this.pause = null; |
| 190 | this.log(`backpressure released after ${Date.now() - t0}ms: wal=${this.mb(this.db.getWalSizeBytes())} baseline=${this.mb(this.sizeAtLastFullBackfill)}`); |
| 191 | }); |
| 192 | return this.pause; |
| 193 | } |
| 194 | |
| 195 | /** Await any in-flight checkpoint and writer pause. */ |
| 196 | async drain(): Promise<void> { |
no test coverage detected