feat(immich): wire cron-fired scheduled/periodic/memory dispatch
The scheduled_enabled / scheduled_times (and the periodic / memory counterparts) on TrackingConfig had been wired into the model, the API, and the test-dispatch path — but no production scheduler ever read them, so users saw the slot in the UI and only ever got fires through "Test". This adds the missing cron jobs and the dispatch fan-out, both keyed off the app-level IANA timezone. * services/scheduled_dispatch.py — production fan-out reusing the test-path event builders, picking the slot template per kind, and writing an EventLog row per fire so the dashboard reflects it. * services/scheduler.py — _load_immich_dispatch_jobs builds one CronTrigger per (tracker, kind, HH:MM) from the tracker's default TrackingConfig; reschedule_immich_dispatch_jobs rebuilds them all on any relevant CRUD or timezone change. * tracker / link / tracking-config CRUD endpoints now invalidate. Also: skip dispatch when scheduled/memory yield zero matching assets (prevents header-only "On this day:" spam), and update the EN/RU default scheduled_assets templates to surface that the delivery is a scheduled random selection.
This commit is contained in:
@@ -23,6 +23,7 @@ from ..database.models import (
|
||||
)
|
||||
from ..services.notifier import send_test_notification
|
||||
from ..services.manual_dispatch import dispatch_test_notification
|
||||
from ..services.scheduler import reschedule_immich_dispatch_jobs
|
||||
from .helpers import get_owned_entity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -118,6 +119,7 @@ async def create_notification_tracker_target(
|
||||
session.add(tt)
|
||||
await session.commit()
|
||||
await session.refresh(tt)
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
return await _tt_response(session, tt)
|
||||
|
||||
|
||||
@@ -164,6 +166,7 @@ async def update_notification_tracker_target(
|
||||
session.add(tt)
|
||||
await session.commit()
|
||||
await session.refresh(tt)
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
return await _tt_response(session, tt)
|
||||
|
||||
|
||||
@@ -181,6 +184,7 @@ async def delete_notification_tracker_target(
|
||||
raise HTTPException(status_code=404, detail="Tracker-target link not found")
|
||||
await session.delete(tt)
|
||||
await session.commit()
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
|
||||
|
||||
@router.post("/{tracker_target_id}/test/{test_type}")
|
||||
|
||||
@@ -18,7 +18,11 @@ from ..database.models import (
|
||||
ServiceProvider,
|
||||
User,
|
||||
)
|
||||
from ..services.scheduler import schedule_tracker, unschedule_tracker
|
||||
from ..services.scheduler import (
|
||||
reschedule_immich_dispatch_jobs,
|
||||
schedule_tracker,
|
||||
unschedule_tracker,
|
||||
)
|
||||
from .helpers import get_owned_entity
|
||||
from .notification_tracker_targets import _tt_response
|
||||
|
||||
@@ -146,6 +150,7 @@ async def create_notification_tracker(
|
||||
await session.refresh(tracker)
|
||||
if tracker.enabled:
|
||||
await schedule_tracker(tracker.id, tracker.scan_interval)
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
return await _tracker_response(session, tracker)
|
||||
|
||||
|
||||
@@ -176,6 +181,7 @@ async def update_notification_tracker(
|
||||
await schedule_tracker(tracker.id, tracker.scan_interval)
|
||||
else:
|
||||
await unschedule_tracker(tracker.id)
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
return await _tracker_response(session, tracker)
|
||||
|
||||
|
||||
@@ -208,6 +214,7 @@ async def delete_notification_tracker(
|
||||
await session.delete(tracker)
|
||||
await session.commit()
|
||||
await unschedule_tracker(tracker_id)
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
|
||||
|
||||
@router.post("/{tracker_id}/trigger")
|
||||
|
||||
@@ -10,6 +10,7 @@ from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from ..auth.dependencies import get_current_user
|
||||
from ..database.engine import get_session
|
||||
from ..database.models import TrackingConfig, User
|
||||
from ..services.scheduler import reschedule_immich_dispatch_jobs
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -127,6 +128,8 @@ async def create_config(
|
||||
session.add(config)
|
||||
await session.commit()
|
||||
await session.refresh(config)
|
||||
if config.provider_type == "immich":
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
return _response(config)
|
||||
|
||||
|
||||
@@ -152,6 +155,8 @@ async def update_config(
|
||||
session.add(config)
|
||||
await session.commit()
|
||||
await session.refresh(config)
|
||||
if config.provider_type == "immich":
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
return _response(config)
|
||||
|
||||
|
||||
@@ -164,8 +169,11 @@ async def delete_config(
|
||||
from .delete_protection import check_tracking_config, raise_if_used
|
||||
config = await _get(session, config_id, user.id)
|
||||
raise_if_used(await check_tracking_config(session, config.id), config.name)
|
||||
provider_type = config.provider_type
|
||||
await session.delete(config)
|
||||
await session.commit()
|
||||
if provider_type == "immich":
|
||||
await reschedule_immich_dispatch_jobs()
|
||||
|
||||
|
||||
def _response(c: TrackingConfig) -> dict:
|
||||
|
||||
Reference in New Issue
Block a user