Limit recording retention to available storage (#3942)

* Add field and migration for segment size

* Store the segment size in db

* Add comment

* Add default

* Fix size parsing

* Include segment size in recordings endpoint

* Start adding storage maintainer

* Add storage maintainer and calculate average sizes

* Update comment

* Store segment and hour avg sizes per camera

* Formatting

* Keep track of total segment and hour averages

* Remove unused files

* Cleanup 2 hours of recordings at a time

* Formatting

* Fix bug

* Round segment size

* Cleanup some comments

* Handle case where segments are not deleted on initial run or is only retained segments

* Improve cleanup log

* Formatting

* Fix typo and improve logging

* Catch case where no recordings exist for camera

* Specifically define sort

* Handle edge case for cameras that only record part time

* Increase definition of part time recorder

* Remove warning about not supported storage based retention

* Add note about storage based retention to recording docs

* Add tests for storage maintenance calculation and cleanup

* Format tests

* Don't run for a camera with no recording segments

* Get size of file from cache

* Rework camera stats to be more efficient

* Remove total and other inefficencies

* Rewrite storage cleanup logic to be much more efficient

* Fix existing tests

* Fix bugs from tests

* Add another test

* Improve logging

* Formatting

* Set back correct loop time

* Update name

* Update comment

* Only include segments that have a nonzero size

* Catch case where camera has 0 nonzero segment durations

* Add test to cover zero bandwidth migration case

* Fix test

* Incorrect boolean logic

* Formatting

* Explicity re-define iterator
This commit is contained in:
Nicolas Mowen
2022-10-09 05:28:26 -06:00
committed by GitHub
parent 3c01dbed7d
commit b4d4adb75b
9 changed files with 485 additions and 21 deletions

View File

@@ -284,6 +284,15 @@ class RecordingMaintainer(threading.Thread):
f"Copied {file_path} in {datetime.datetime.now().timestamp()-start_frame} seconds."
)
try:
segment_size = round(
float(os.path.getsize(cache_path)) / 1000000, 1
)
except OSError:
segment_size = 0
os.remove(cache_path)
rand_id = "".join(
random.choices(string.ascii_lowercase + string.digits, k=6)
)
@@ -297,10 +306,8 @@ class RecordingMaintainer(threading.Thread):
motion=motion_count,
# TODO: update this to store list of active objects at some point
objects=active_count,
segment_size=segment_size,
)
else:
logger.warning(f"Ignoring segment because {file_path} already exists.")
os.remove(cache_path)
except Exception as e:
logger.error(f"Unable to store recording segment {cache_path}")
Path(cache_path).unlink(missing_ok=True)