video: hourly 'Update Video Database' safety net (the second-trigger pattern)
dual triggers on one automation aren't a thing (one trigger per row, same as music), so this adds a second automation sharing the handler — like Auto-Deep Scan TV/Movie already do. 'Auto-Update Video Database (Hourly)' runs the same cheap incremental server-read on an hourly schedule, so MANUAL library additions (which Plex auto-scans) appear within the hour instead of waiting for the weekly deep scan; the existing after-scan one still gives instant updates for SoulSync-initiated scans. new action_type video_update_database_hourly (seeder keys on action_type) reusing auto_video_update_database in incremental mode; registered, seeded (schedule 1h, 15m initial delay), UI block, label/icon, sort order. tested.
This commit is contained in:
parent
11c0c62a7e
commit
151bb7b542
6 changed files with 35 additions and 3 deletions
|
|
@ -253,6 +253,8 @@ ACTIONS: list[dict] = [
|
|||
{"value": "show", "label": "TV only"}],
|
||||
"default": "all"}
|
||||
]},
|
||||
{"type": "video_update_database_hourly", "label": "Update Video Database (Hourly)", "icon": "database", "scope": "video",
|
||||
"description": "The same incremental server-read on an hourly schedule, so manual library additions (which Plex auto-scans) appear within the hour instead of waiting for the weekly deep scan. Pair with a 1-hour Schedule trigger.", "available": True},
|
||||
# Per-library deep-scan presets (the system 'Auto-Deep Scan TV/Movie Library' run
|
||||
# these). Scope + deep mode are baked in by the registration wrapper, so no config
|
||||
# fields — drag one in and it just deep-scans that library.
|
||||
|
|
|
|||
|
|
@ -228,6 +228,13 @@ def register_all(deps: AutomationDeps) -> None:
|
|||
'video_update_database',
|
||||
lambda config: auto_video_update_database(config, deps),
|
||||
)
|
||||
# Same incremental update, but on an hourly SCHEDULE (not just after a SoulSync scan) —
|
||||
# so manual library additions (which Plex auto-scans) show up within the hour instead of
|
||||
# waiting for the weekly deep scan. A distinct action_type because the seeder keys on it.
|
||||
engine.register_action_handler(
|
||||
'video_update_database_hourly',
|
||||
lambda config: auto_video_update_database({'mode': 'incremental', **config}, deps),
|
||||
)
|
||||
# Sonarr-style: wishlist every episode airing today (for followed shows).
|
||||
engine.register_action_handler(
|
||||
'video_add_airing_episodes',
|
||||
|
|
|
|||
|
|
@ -170,6 +170,18 @@ SYSTEM_AUTOMATIONS = [
|
|||
'action_config': {'mode': 'incremental'},
|
||||
'owned_by': 'video',
|
||||
},
|
||||
# Safety net: re-read the server hourly too, so MANUAL library additions (which Plex
|
||||
# auto-scans) appear within the hour instead of waiting for the weekly deep scan. Same
|
||||
# cheap incremental read as the after-scan one.
|
||||
{
|
||||
'name': 'Auto-Update Video Database (Hourly)',
|
||||
'trigger_type': 'schedule',
|
||||
'trigger_config': {'interval': 1, 'unit': 'hours'},
|
||||
'action_type': 'video_update_database_hourly',
|
||||
'action_config': {'mode': 'incremental'},
|
||||
'initial_delay': 900,
|
||||
'owned_by': 'video',
|
||||
},
|
||||
# Sonarr-style: once a day at 1am (server-local), wishlist every episode airing
|
||||
# today for the shows you follow (skipping ones already owned) so the day's episodes
|
||||
# are queued overnight. A fixed wall-clock 'daily_time' (not a rolling 24h interval
|
||||
|
|
|
|||
|
|
@ -120,6 +120,16 @@ def test_every_video_automation_has_a_friendly_label_and_icon():
|
|||
assert not missing, "video actions missing a label/icon: " + ", ".join(sorted(missing))
|
||||
|
||||
|
||||
def test_hourly_db_update_is_a_scheduled_safety_net():
|
||||
# second trigger (a schedule) for the same incremental DB read, so manual library adds
|
||||
# show up within the hour instead of waiting for the weekly deep scan.
|
||||
import core.automation_engine as ae
|
||||
row = next((a for a in ae.SYSTEM_AUTOMATIONS if a.get("action_type") == "video_update_database_hourly"), None)
|
||||
assert row is not None
|
||||
assert row["trigger_type"] == "schedule" and row["trigger_config"]["unit"] == "hours"
|
||||
assert row["action_config"]["mode"] == "incremental" # cheap read, not a deep scan
|
||||
|
||||
|
||||
def test_video_system_automations_are_sorted_by_pipeline_order():
|
||||
# The API returns newest-created-first (jumbled); the page re-sorts by an
|
||||
# explicit order so it reads scans → processors → library → maintenance.
|
||||
|
|
|
|||
|
|
@ -1774,7 +1774,7 @@ const _autoIcons = {
|
|||
full_cleanup: '\uD83E\uDDF9',
|
||||
playlist_pipeline: '\uD83D\uDE80',
|
||||
// Video side
|
||||
video_scan_library: '\uD83C\uDFAC', video_scan_server: '\uD83D\uDD04', video_update_database: '\uD83D\uDDC4\uFE0F',
|
||||
video_scan_library: '\uD83C\uDFAC', video_scan_server: '\uD83D\uDD04', video_update_database: '\uD83D\uDDC4\uFE0F', video_update_database_hourly: '\uD83D\uDDC4\uFE0F',
|
||||
video_add_airing_episodes: '\uD83D\uDCFA', video_deep_scan_movies: '\uD83C\uDFAC', video_deep_scan_tv: '\uD83D\uDCFA',
|
||||
video_scan_watchlist_people: '\uD83C\uDFAD', video_scan_watchlist_channels: '\uD83D\uDCE1',
|
||||
video_scan_watchlist_playlists: '\uD83C\uDFB5',
|
||||
|
|
@ -3375,7 +3375,8 @@ function _autoFormatAction(type) {
|
|||
playlist_pipeline: 'Playlist Pipeline',
|
||||
// Video side
|
||||
video_scan_library: 'Scan Video Library', video_scan_server: 'Scan Video Server',
|
||||
video_update_database: 'Update Video Database', video_add_airing_episodes: 'Wishlist Airing Episodes',
|
||||
video_update_database: 'Update Video Database', video_update_database_hourly: 'Update Video Database (Hourly)',
|
||||
video_add_airing_episodes: 'Wishlist Airing Episodes',
|
||||
video_deep_scan_movies: 'Deep Scan Movie Library', video_deep_scan_tv: 'Deep Scan TV Library',
|
||||
video_scan_watchlist_people: 'Scan Watchlist People',
|
||||
video_scan_watchlist_channels: 'Scan Watchlist Channels',
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
// Stage 2 — processors that DRAIN it (download)
|
||||
'video_process_movie_wishlist', 'video_process_episode_wishlist', 'video_process_youtube_wishlist',
|
||||
// Library scan / sync
|
||||
'video_scan_server', 'video_update_database', 'video_deep_scan_tv', 'video_deep_scan_movies',
|
||||
'video_scan_server', 'video_update_database', 'video_update_database_hourly', 'video_deep_scan_tv', 'video_deep_scan_movies',
|
||||
// Maintenance
|
||||
'video_clean_search_history', 'video_clean_completed_downloads', 'video_full_cleanup', 'video_backup_database',
|
||||
];
|
||||
|
|
|
|||
Loading…
Reference in a new issue