implement caching for TeslaCam directory scan and add refresh endpoint

This commit is contained in:
zwitschi committed 2026-07-24 12:58:58 +02:00
1 parent a4202afe30
commit 829c28ca69
3 files changed
+57 -6

No files matched your search

+35 -1
View File
@@ -11,6 +11,7 @@ play videos from different camera views.
import os
import re
import time
from dotenv import load_dotenv
from flask import Flask, render_template, send_from_directory, abort
@@ -39,8 +40,15 @@ CAMERA_VIEW_MAPPING = {
'right_pillar': 'Right Pillar'
}
# In-memory scan cache. Scanning a large TeslaCam tree on every request is
# expensive, so the result is cached and only refreshed after this many seconds
# (or when /refresh is hit). Override via the SCAN_CACHE_TTL env var.
SCAN_CACHE_TTL = int(os.environ.get('SCAN_CACHE_TTL', '3600'))
def scan_teslacam_videos():
_scan_cache = {'data': None, 'expires_at': 0.0}
def _scan_teslacam_videos_uncached():
"""
Recursively scans the TeslaCam directory tree for video files and categorizes
them by camera view.
@@ -84,6 +92,22 @@ def scan_teslacam_videos():
return videos_by_camera
def scan_teslacam_videos(force_refresh=False):
"""
Returns the cached TeslaCam video scan, refreshing it when the TTL expires
or when `force_refresh` is True. Safe to call on every request.
"""
now = time.time()
if (
_scan_cache['data'] is None
or now >= _scan_cache['expires_at']
or force_refresh
):
_scan_cache['data'] = _scan_teslacam_videos_uncached()
_scan_cache['expires_at'] = now + SCAN_CACHE_TTL
return _scan_cache['data']
def get_camera_display_name(camera_view):
"""Returns human-readable title for a camera view key."""
return CAMERA_VIEW_MAPPING.get(camera_view, camera_view.replace('_', ' ').title())
@@ -137,6 +161,16 @@ def serve_video(filepath):
return send_from_directory(TESLACAM_DIRECTORY, filepath)
@app.route('/refresh')
def refresh():
"""
Forces a re-scan of the TeslaCam directory, bypassing the cache TTL.
Useful after copying new clips onto the drive.
"""
scan_teslacam_videos(force_refresh=True)
return 'Cache refreshed', 200
if __name__ == '__main__':
# Local dev server. For production, run behind a WSGI server instead, e.g.:
# gunicorn -w 4 -b 0.0.0.0:5000 'videoplayer:app'