fix(state): use TRUNCATE WAL checkpoint to prevent unbounded WAL growth
PASSIVE checkpoint never shrinks the WAL file, causing state.db-wal to grow without bound. Change to TRUNCATE in _try_wal_checkpoint() and close() so the WAL is truncated regularly. Fixes #24034
This commit is contained in:
@ -595,17 +595,27 @@ class SessionDB:
|
||||
)
|
||||
|
||||
def _try_wal_checkpoint(self) -> None:
|
||||
"""Best-effort PASSIVE WAL checkpoint. Never blocks, never raises.
|
||||
"""Best-effort TRUNCATE WAL checkpoint. Never raises.
|
||||
|
||||
Flushes committed WAL frames back into the main DB file for any
|
||||
frames that no other connection currently needs. Keeps the WAL
|
||||
from growing unbounded when many processes hold persistent
|
||||
Flushes committed WAL frames back into the main DB file and
|
||||
truncates the WAL file to zero bytes. Keeps the WAL from
|
||||
growing unbounded when many processes hold persistent
|
||||
connections.
|
||||
|
||||
PASSIVE checkpoint was previously used here, but it never
|
||||
truncates the WAL file — the file stays at its high-water
|
||||
mark until an explicit TRUNCATE is called (which only
|
||||
happened inside the infrequent vacuum()).
|
||||
|
||||
TRUNCATE may block writers briefly while checkpointing, but
|
||||
_try_wal_checkpoint is called off the hot path (every 50
|
||||
writes) and already runs under ``self._lock``, so the
|
||||
additional hold time is negligible.
|
||||
"""
|
||||
try:
|
||||
with self._lock:
|
||||
result = self._conn.execute(
|
||||
"PRAGMA wal_checkpoint(PASSIVE)"
|
||||
"PRAGMA wal_checkpoint(TRUNCATE)"
|
||||
).fetchone()
|
||||
if result and result[1] > 0:
|
||||
logger.debug(
|
||||
@ -618,13 +628,13 @@ class SessionDB:
|
||||
def close(self):
|
||||
"""Close the database connection.
|
||||
|
||||
Attempts a PASSIVE WAL checkpoint first so that exiting processes
|
||||
help keep the WAL file from growing unbounded.
|
||||
Attempts a TRUNCATE WAL checkpoint first so that exiting processes
|
||||
help shrink the WAL file.
|
||||
"""
|
||||
with self._lock:
|
||||
if self._conn:
|
||||
try:
|
||||
self._conn.execute("PRAGMA wal_checkpoint(PASSIVE)")
|
||||
self._conn.execute("PRAGMA wal_checkpoint(TRUNCATE)")
|
||||
except Exception:
|
||||
pass
|
||||
self._conn.close()
|
||||
|
||||
Reference in New Issue
Block a user