Clean up previews more efficiently

This commit is contained in:
Nick Mowen 2023-11-30 07:28:45 -07:00
parent 8765c513cd
commit 337f07508e

View File

@ -62,6 +62,7 @@ class RecordingCleanup(threading.Thread):
# TODO: expire segments based on segment stats according to config # TODO: expire segments based on segment stats according to config
event_start = 0 event_start = 0
deleted_recordings = set() deleted_recordings = set()
kept_recordings: list[tuple[float, float]] = []
for recording in recordings: for recording in recordings:
keep = False keep = False
# Now look for a reason to keep this recording segment # Now look for a reason to keep this recording segment
@ -101,7 +102,10 @@ class RecordingCleanup(threading.Thread):
): ):
Path(recording.path).unlink(missing_ok=True) Path(recording.path).unlink(missing_ok=True)
deleted_recordings.add(recording.id) deleted_recordings.add(recording.id)
else:
kept_recordings.append((recording.start_time, recording.end_time))
# expire recordings
logger.debug(f"Expiring {len(deleted_recordings)} recordings") logger.debug(f"Expiring {len(deleted_recordings)} recordings")
# delete up to 100,000 at a time # delete up to 100,000 at a time
max_deletes = 100000 max_deletes = 100000
@ -111,11 +115,6 @@ class RecordingCleanup(threading.Thread):
Recordings.id << deleted_recordings_list[i : i + max_deletes] Recordings.id << deleted_recordings_list[i : i + max_deletes]
).execute() ).execute()
def expire_existing_camera_previews(
self, expire_date: float, config: CameraConfig, events: Event
) -> None:
"""Delete previews for existing camera based on record retention config."""
# Get previews to check for expiration
previews: Previews = ( previews: Previews = (
Previews.select( Previews.select(
Previews.id, Previews.id,
@ -129,44 +128,43 @@ class RecordingCleanup(threading.Thread):
) )
.order_by(Previews.start_time) .order_by(Previews.start_time)
.namedtuples() .namedtuples()
.iterator()
) )
# loop over previews and see if they overlap with any non-expired events # expire previews
# TODO: expire segments based on segment stats according to config recording_start = 0
event_start = 0
deleted_previews = set() deleted_previews = set()
for preview in previews: for preview in previews:
keep = False keep = False
# Now look for a reason to keep this previews segment # look for a reason to keep this preview
for idx in range(event_start, len(events)): for idx in range(recording_start, len(kept_recordings)):
event: Event = events[idx] start_time, end_time = kept_recordings[idx]
# if the event starts in the future, stop checking events # if the recording starts in the future, stop checking recordings
# and let this preview expire # and let this preview expire
if event.start_time > preview.end_time: if start_time > preview.end_time:
keep = False keep = False
break break
# if the event is in progress or ends after the preview starts, keep it # if the recording ends after the preview starts, keep it
# and stop looking at events # and stop looking at recordings
if event.end_time is None or event.end_time >= preview.start_time: if end_time >= preview.start_time:
keep = True keep = True
break break
# if the event ends before this preview starts, skip # if the recording ends before this preview starts, skip
# this event and check the next event for an overlap. # this recording and check the next recording for an overlap.
# since the events and recordings are sorted, we can skip events # since the kept recordings and previews are sorted, we can skip recordings
# that end before the previous preview started on future previews # that end before the current preview started
if event.end_time < preview.start_time: if end_time < preview.start_time:
event_start = idx recording_start = idx
# Delete previews outside of the retention window or based on the retention mode # Delete previews without any relevant recordings
if not keep: if not keep:
Path(preview.path).unlink(missing_ok=True) Path(preview.path).unlink(missing_ok=True)
deleted_previews.add(preview.id) deleted_previews.add(preview.id)
logger.debug(f"Expiring {len(deleted_previews)} recordings") # expire previews
logger.debug(f"Expiring {len(deleted_previews)} previews")
# delete up to 100,000 at a time # delete up to 100,000 at a time
max_deletes = 100000 max_deletes = 100000
deleted_previews_list = list(deleted_previews) deleted_previews_list = list(deleted_previews)
@ -240,7 +238,6 @@ class RecordingCleanup(threading.Thread):
) )
self.expire_existing_camera_recordings(expire_date, config, events) self.expire_existing_camera_recordings(expire_date, config, events)
self.expire_existing_camera_previews(expire_date, config, events)
logger.debug(f"End camera: {camera}.") logger.debug(f"End camera: {camera}.")
logger.debug("End all cameras.") logger.debug("End all cameras.")