Add RetainPolicyEnum and retain_policy config field for NVR-style storage

Introduce a new RetainPolicyEnum with 'time' (default, existing behavior)
and 'continuous_rollover' (fill disk, overwrite oldest) options. Add the
retain_policy field to RecordConfig and include unit tests for config
validation.
This commit is contained in:
jon 2026-03-01 12:17:06 -06:00
parent 4232cc483d
commit aed3793ce1
2 changed files with 60 additions and 0 deletions

View File

@ -17,6 +17,7 @@ __all__ = [
"ReviewRetainConfig",
"RecordRetainConfig",
"RetainModeEnum",
"RetainPolicyEnum",
]
@ -35,6 +36,11 @@ class RetainModeEnum(str, Enum):
active_objects = "active_objects"
class RetainPolicyEnum(str, Enum):
time = "time"
continuous_rollover = "continuous_rollover"
class ReviewRetainConfig(FrigateBaseModel):
days: float = Field(
default=10,
@ -100,6 +106,11 @@ class RecordConfig(FrigateBaseModel):
title="Enable recording",
description="Enable or disable recording for all cameras; can be overridden per-camera.",
)
retain_policy: RetainPolicyEnum = Field(
default=RetainPolicyEnum.time,
title="Retention policy",
description="Storage retention policy. 'time' expires recordings after configured days. 'continuous_rollover' fills available disk space and overwrites oldest recordings when space is needed.",
)
expire_interval: int = Field(
default=60,
title="Record cleanup interval",

View File

@ -0,0 +1,49 @@
import unittest
from frigate.config import FrigateConfig
class TestRetainPolicyConfig(unittest.TestCase):
def setUp(self):
self.base_config = {
"mqtt": {"host": "mqtt"},
"cameras": {
"front_door": {
"ffmpeg": {
"inputs": [
{"path": "rtsp://10.0.0.1:554/video", "roles": ["detect"]}
]
},
"detect": {"height": 1080, "width": 1920, "fps": 5},
}
},
}
def test_default_retain_policy_is_time(self):
config = FrigateConfig(**self.base_config)
assert config.record.retain_policy.value == "time"
def test_continuous_rollover_policy(self):
self.base_config["record"] = {
"enabled": True,
"retain_policy": "continuous_rollover",
}
config = FrigateConfig(**self.base_config)
assert config.record.retain_policy.value == "continuous_rollover"
def test_continuous_rollover_ignores_continuous_days(self):
self.base_config["record"] = {
"enabled": True,
"retain_policy": "continuous_rollover",
"continuous": {"days": 30},
}
config = FrigateConfig(**self.base_config)
assert config.record.retain_policy.value == "continuous_rollover"
assert config.record.continuous.days == 30
def test_invalid_retain_policy_rejected(self):
self.base_config["record"] = {
"retain_policy": "invalid_value",
}
with self.assertRaises(Exception):
FrigateConfig(**self.base_config)