Video automations: reliably delete the obsolete 'Scan Video Library' seed

_fix_video_scan_default set its 'done' flag even on runs where it deleted
nothing, so once the flag latched True the standalone 'Scan Video Library'
system automation survived forever (the row the post-download chain replaced).
Drop the flag entirely — get_system_automation_by_action already matches only
the is_system-seeded row, so the cleanup is safe to run every startup and
no-ops once the row is gone.
This commit is contained in:
BoulderBadgeDad 2026-06-21 08:59:32 -07:00
parent 5711963a6f
commit fd66390648
2 changed files with 24 additions and 26 deletions

View file

@ -325,20 +325,21 @@ class AutomationEngine:
self._fix_video_scan_default()
def _fix_video_scan_default(self):
"""One-time cleanup: remove the standalone 'Scan Video Library' system
automation it's superseded by the post-download chain (Auto-Scan Video
After Downloads Auto-Update Video Database After Scan). Only deletes the
SYSTEM row; a user can still build their own scan automation from the action.
Flag-guarded so it runs once."""
"""Remove the obsolete standalone 'Scan Video Library' SYSTEM automation — it's
superseded by the post-download chain (Auto-Scan Video After Downloads
Auto-Update Video Database After Scan).
``get_system_automation_by_action`` matches ONLY a system-seeded row
(is_system=1), so a user's own scan automation is never touched. Idempotent —
safe to run on every startup; once the row is gone the lookup returns None and
it no-ops. (No flag guard: the old one could latch True without ever deleting,
which is exactly why the row survived earlier 'cleanups'.)"""
try:
from config.settings import config_manager
if config_manager.get('video_scan_cleanup_v3', False):
return
auto = self.db.get_system_automation_by_action('video_scan_library')
if auto and auto.get('is_system'):
if auto:
self.db.delete_automation(auto['id'])
logger.info("Removed superseded 'Scan Video Library' system automation")
config_manager.set('video_scan_cleanup_v3', True)
logger.info("Removed superseded 'Scan Video Library' system automation (id=%s)",
auto.get('id'))
except Exception:
logger.exception("video scan cleanup failed")

View file

@ -438,21 +438,18 @@ def test_ensure_system_automations_seeds_video_with_owned_by_and_mode():
assert json.loads(created['scan_library']['action_config']) == {}
def test_video_scan_library_system_automation_is_cleaned_up(monkeypatch):
"""The old standalone 'Scan Video Library' system automation is deleted once
(superseded by the post-download chain). Guard flag stops it re-running."""
class _FakeCfg:
def __init__(self): self._d = {}
def get(self, k, default=None): return self._d.get(k, default)
def set(self, k, v): self._d[k] = v
monkeypatch.setattr('config.settings.config_manager', _FakeCfg())
def test_video_scan_library_system_automation_is_cleaned_up():
"""The obsolete standalone 'Scan Video Library' system automation is deleted when
present (superseded by the post-download chain). No stuck flag it just keys off
the lookup, so once the row is gone it no-ops."""
# present → deleted (matches only the is_system-seeded row)
db = MagicMock()
db.get_system_automation_by_action.return_value = {'id': 99, 'is_system': 1}
engine = AutomationEngine(db)
AutomationEngine(db)._fix_video_scan_default()
db.delete_automation.assert_any_call(99)
engine._fix_video_scan_default()
db.delete_automation.assert_called_once_with(99)
engine._fix_video_scan_default() # flag set → no second delete
db.delete_automation.assert_called_once()
# absent (already gone) → idempotent no-op, never errors or deletes
db2 = MagicMock()
db2.get_system_automation_by_action.return_value = None
AutomationEngine(db2)._fix_video_scan_default()
db2.delete_automation.assert_not_called()