From f6ff1c84b8800f60a841e0c527673ac5513fddf8 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Sun, 7 Apr 2024 14:37:12 -0600 Subject: [PATCH] Truncate write ahead log if it gets too big (#10866) * Truncate write ahead log if it gets too big * formatting * Reduce size --- frigate/const.py | 4 ++++ frigate/record/cleanup.py | 23 ++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/frigate/const.py b/frigate/const.py index 9b65fe5c9..28ab83c8a 100644 --- a/frigate/const.py +++ b/frigate/const.py @@ -39,6 +39,10 @@ AUDIO_MAX_BIT_RANGE = 32768.0 AUDIO_SAMPLE_RATE = 16000 AUDIO_MIN_CONFIDENCE = 0.5 +# DB Consts + +MAX_WAL_SIZE = 10 # MB + # Ffmpeg Presets FFMPEG_HWACCEL_NVIDIA = "preset-nvidia" diff --git a/frigate/record/cleanup.py b/frigate/record/cleanup.py index 86f1e63e1..c45ea032d 100644 --- a/frigate/record/cleanup.py +++ b/frigate/record/cleanup.py @@ -3,12 +3,15 @@ import datetime import itertools import logging +import os import threading from multiprocessing.synchronize import Event as MpEvent from pathlib import Path +from playhouse.sqlite_ext import SqliteExtDatabase + from frigate.config import CameraConfig, FrigateConfig, RetainModeEnum -from frigate.const import CACHE_DIR, RECORD_DIR +from frigate.const import CACHE_DIR, MAX_WAL_SIZE, RECORD_DIR from frigate.models import Event, Previews, Recordings, ReviewSegment from frigate.record.util import remove_empty_directories, sync_recordings from frigate.util.builtin import clear_and_unlink, get_tomorrow_at_time @@ -33,6 +36,23 @@ class RecordingCleanup(threading.Thread): logger.debug("Deleting tmp clip.") clear_and_unlink(p) + def truncate_wal(self) -> None: + """check if the WAL needs to be manually truncated.""" + + # by default the WAL should be check-pointed automatically + # however, high levels of activity can prevent an opportunity + # for the checkpoint to be finished which means the WAL will grow + # without bound + + # with auto checkpoint most users should never hit this + + if ( + os.stat(f"{self.config.database.path}-wal").st_size / (1024 * 1024) + ) > MAX_WAL_SIZE: + db = SqliteExtDatabase(self.config.database.path) + db.execute_sql("PRAGMA wal_checkpoint(TRUNCATE);") + db.close() + def expire_existing_camera_recordings( self, expire_date: float, config: CameraConfig, events: Event ) -> None: @@ -328,3 +348,4 @@ class RecordingCleanup(threading.Thread): if counter == 0: self.expire_recordings() remove_empty_directories(RECORD_DIR) + self.truncate_wal()