This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Run plex-label-sync on a cron schedule from env."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from croniter import croniter
|
||||
|
||||
CRON_MACROS = {
|
||||
'@yearly': '0 0 1 1 *',
|
||||
'@annually': '0 0 1 1 *',
|
||||
'@monthly': '0 0 1 * *',
|
||||
'@weekly': '0 0 * * 0',
|
||||
'@daily': '0 0 * * *',
|
||||
'@midnight': '0 0 * * *',
|
||||
'@hourly': '0 * * * *',
|
||||
}
|
||||
|
||||
|
||||
def log(msg: str) -> None:
|
||||
print(f"[{datetime.now().astimezone().isoformat(timespec='seconds')}] {msg}", flush=True)
|
||||
|
||||
|
||||
def zone() -> ZoneInfo:
|
||||
name = os.environ.get('TZ') or 'UTC'
|
||||
try:
|
||||
return ZoneInfo(name)
|
||||
except Exception as exc:
|
||||
raise SystemExit(f"Invalid TZ '{name}': {exc}") from exc
|
||||
|
||||
|
||||
def resolve_cron_expr() -> str:
|
||||
for key in ('CRON_SCHEDULE', 'CRON', 'SYNC_CRON'):
|
||||
value = os.environ.get(key, '').strip()
|
||||
if value:
|
||||
expr = CRON_MACROS.get(value.lower(), value)
|
||||
if not croniter.is_valid(expr):
|
||||
raise SystemExit(
|
||||
f"Invalid {key} '{value}' (expected a 5-field cron expression)"
|
||||
)
|
||||
return expr
|
||||
return '0 */6 * * *'
|
||||
|
||||
|
||||
def next_run(expr: str, after: datetime) -> datetime:
|
||||
return croniter(expr, after).get_next(datetime)
|
||||
|
||||
|
||||
def run_sync() -> int:
|
||||
log('Starting sync…')
|
||||
result = subprocess.run([sys.executable, '/app/sync.py'], check=False)
|
||||
log(f'Sync finished with code {result.returncode}.')
|
||||
return result.returncode
|
||||
|
||||
|
||||
def main() -> int:
|
||||
tz = zone()
|
||||
expr = resolve_cron_expr()
|
||||
run_on_start = os.environ.get('RUN_ON_START', 'true').lower() in {'1', 'true', 'yes'}
|
||||
|
||||
log(f"plex-label-sync scheduler (TZ={tz.key}, CRON_SCHEDULE='{expr}')")
|
||||
|
||||
if run_on_start:
|
||||
run_sync()
|
||||
|
||||
while True:
|
||||
now = datetime.now(tz=tz)
|
||||
nxt = next_run(expr, now)
|
||||
sleep_for = max(1.0, (nxt - now).total_seconds())
|
||||
log(f"Next run at {nxt.isoformat(timespec='seconds')} (sleep {sleep_for:.0f}s)")
|
||||
time.sleep(sleep_for)
|
||||
run_sync()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user