video automations: migrate the Download->Process rename in seeded DBs
bug: renaming the action_types only changed code — a db already seeded under the old names kept the stale rows (the seeder only CREATES missing ones, never removes or renames). so on restart you got BOTH 'Auto-Download Movie Wishlist' (orphaned, dead action) AND 'Auto-Process Movie Wishlist'. add _fix_wishlist_processor_rename (runs in ensure_system_automations like the other _fix_* migrations): deletes the orphaned video_download_movie/episode_wishlist system rows (clearing is_system first, since delete_automation guards system rows) and renames the youtube row in place (its action_type was unchanged). idempotent. tested.
This commit is contained in:
parent
7d7d242e5d
commit
10895a7c16
2 changed files with 62 additions and 0 deletions
|
|
@ -453,6 +453,7 @@ class AutomationEngine:
|
|||
self._fix_video_scan_default()
|
||||
self._fix_airing_automation_schedule()
|
||||
self._fix_deep_scan_schedules()
|
||||
self._fix_wishlist_processor_rename()
|
||||
|
||||
def _fix_video_scan_default(self):
|
||||
"""Remove the obsolete standalone 'Scan Video Library' SYSTEM automation — it's
|
||||
|
|
@ -473,6 +474,31 @@ class AutomationEngine:
|
|||
except Exception:
|
||||
logger.exception("video scan cleanup failed")
|
||||
|
||||
def _fix_wishlist_processor_rename(self):
|
||||
"""Migrate the wishlist processors' 'Download' → 'Process' rename so a DB seeded
|
||||
under the old names doesn't show stale duplicates.
|
||||
|
||||
The movie/episode ACTIONS were renamed (``video_download_*`` → ``video_process_*``),
|
||||
so the old seeded rows are now orphaned (dead action_type) while the new ones reseed
|
||||
alongside them — delete the orphans. ``delete_automation`` refuses system rows, so
|
||||
clear ``is_system`` first. The YouTube action kept its type but its label changed, so
|
||||
rename that row in place. Idempotent — no-ops once the DB is clean."""
|
||||
try:
|
||||
for dead in ('video_download_movie_wishlist', 'video_download_episode_wishlist'):
|
||||
auto = self.db.get_system_automation_by_action(dead)
|
||||
if auto:
|
||||
self.db.update_automation(auto['id'], is_system=0) # lift the delete guard
|
||||
self.db.delete_automation(auto['id'])
|
||||
logger.info("Removed orphaned '%s' system automation (renamed to process, id=%s)",
|
||||
auto.get('name'), auto.get('id'))
|
||||
yt = self.db.get_system_automation_by_action('video_process_youtube_wishlist')
|
||||
if yt and yt.get('name') == 'Auto-Download YouTube Wishlist':
|
||||
self.db.update_automation(yt['id'], name='Auto-Process YouTube Wishlist')
|
||||
logger.info("Renamed YouTube wishlist automation → 'Auto-Process YouTube Wishlist' (id=%s)",
|
||||
yt.get('id'))
|
||||
except Exception:
|
||||
logger.exception("wishlist processor rename migration failed")
|
||||
|
||||
def _fix_airing_automation_schedule(self):
|
||||
"""Migrate 'Auto-Wishlist Episodes Airing Today' from the old rolling 24h
|
||||
interval to a fixed daily 1am run.
|
||||
|
|
|
|||
|
|
@ -528,3 +528,39 @@ def test_deep_scan_migration_is_idempotent_and_safe_when_absent():
|
|||
db2.get_system_automation_by_action.return_value = None
|
||||
AutomationEngine(db2)._fix_deep_scan_schedules()
|
||||
db2.update_automation.assert_not_called()
|
||||
|
||||
|
||||
def test_wishlist_processor_rename_removes_orphans_and_renames_youtube():
|
||||
"""The Download→Process rename: a DB seeded under the old names has orphaned
|
||||
'Auto-Download Movie/Episode Wishlist' rows (dead action_type) — they're deleted (after
|
||||
lifting the is_system delete-guard); the YouTube row (action_type unchanged) is renamed
|
||||
in place, never deleted."""
|
||||
rows = {
|
||||
'video_download_movie_wishlist': {'id': 10, 'is_system': 1, 'name': 'Auto-Download Movie Wishlist'},
|
||||
'video_download_episode_wishlist': {'id': 11, 'is_system': 1, 'name': 'Auto-Download Episode Wishlist'},
|
||||
'video_process_youtube_wishlist': {'id': 12, 'is_system': 1, 'name': 'Auto-Download YouTube Wishlist'},
|
||||
}
|
||||
db = MagicMock()
|
||||
db.get_system_automation_by_action.side_effect = lambda a: rows.get(a)
|
||||
AutomationEngine(db)._fix_wishlist_processor_rename()
|
||||
|
||||
db.delete_automation.assert_any_call(10)
|
||||
db.delete_automation.assert_any_call(11)
|
||||
# is_system=0 lifted on each orphan before deleting
|
||||
cleared = {c.args[0] for c in db.update_automation.call_args_list if c.kwargs.get('is_system') == 0}
|
||||
assert cleared == {10, 11}
|
||||
# youtube renamed (in place), NOT deleted
|
||||
renamed = [c for c in db.update_automation.call_args_list if c.kwargs.get('name')]
|
||||
assert renamed and renamed[0].args[0] == 12
|
||||
assert renamed[0].kwargs['name'] == 'Auto-Process YouTube Wishlist'
|
||||
assert all(c.args[0] != 12 for c in db.delete_automation.call_args_list)
|
||||
|
||||
|
||||
def test_wishlist_processor_rename_is_idempotent_when_clean():
|
||||
# orphans already gone + youtube already renamed → no deletes, no rename
|
||||
rows = {'video_process_youtube_wishlist': {'id': 12, 'is_system': 1, 'name': 'Auto-Process YouTube Wishlist'}}
|
||||
db = MagicMock()
|
||||
db.get_system_automation_by_action.side_effect = lambda a: rows.get(a)
|
||||
AutomationEngine(db)._fix_wishlist_processor_rename()
|
||||
db.delete_automation.assert_not_called()
|
||||
assert not any(c.kwargs.get('name') for c in db.update_automation.call_args_list)
|
||||
|
|
|
|||
Loading…
Reference in a new issue