mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-31 19:45:15 +02:00
feat(automations): static_inputs on triggers + vertical-slice api/services
This commit is contained in:
parent
84d99f19a2
commit
27ab367a13
27 changed files with 915 additions and 356 deletions
|
|
@ -9,8 +9,7 @@ from .params import ManualTriggerParams
|
|||
MANUAL_TRIGGER = TriggerDefinition(
|
||||
type="manual",
|
||||
description="Fire on a user-initiated 'Run now' invocation.",
|
||||
params_schema=ManualTriggerParams.model_json_schema(),
|
||||
payload_schema={"type": "object"},
|
||||
params_model=ManualTriggerParams,
|
||||
)
|
||||
|
||||
register_trigger(MANUAL_TRIGGER)
|
||||
|
|
|
|||
|
|
@ -19,9 +19,14 @@ async def dispatch_manual_run(
|
|||
*,
|
||||
session: AsyncSession,
|
||||
automation_id: int,
|
||||
payload: dict[str, Any] | None,
|
||||
runtime_inputs: dict[str, Any] | None,
|
||||
) -> AutomationRun:
|
||||
"""Find the automation + its enabled manual trigger, then run the generic dispatch."""
|
||||
"""Find the automation + its enabled manual trigger, then run the generic dispatch.
|
||||
|
||||
``runtime_inputs`` is the caller-supplied payload (e.g. an HTTP body for a
|
||||
"Run now" API call); it is merged with the trigger's ``static_inputs`` by
|
||||
the generic dispatcher, with static winning on key collision.
|
||||
"""
|
||||
automation = await _load_automation(session, automation_id)
|
||||
if automation is None:
|
||||
raise DispatchError(f"automation {automation_id} not found")
|
||||
|
|
@ -41,7 +46,7 @@ async def dispatch_manual_run(
|
|||
session=session,
|
||||
automation=automation,
|
||||
trigger=trigger,
|
||||
payload=payload,
|
||||
runtime_inputs=runtime_inputs,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,12 +9,7 @@ from .params import ScheduleTriggerParams
|
|||
SCHEDULE_TRIGGER = TriggerDefinition(
|
||||
type="schedule",
|
||||
description="Fire on a cron schedule in a given timezone.",
|
||||
params_schema=ScheduleTriggerParams.model_json_schema(),
|
||||
payload_schema={
|
||||
"type": "object",
|
||||
"additionalProperties": False,
|
||||
"properties": {},
|
||||
},
|
||||
params_model=ScheduleTriggerParams,
|
||||
)
|
||||
|
||||
register_trigger(SCHEDULE_TRIGGER)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
|
|
@ -16,9 +18,18 @@ async def dispatch_schedule_run(
|
|||
*,
|
||||
session: AsyncSession,
|
||||
trigger: AutomationTrigger,
|
||||
fired_at: datetime,
|
||||
scheduled_for: datetime,
|
||||
previous_last_fired_at: datetime | None,
|
||||
) -> AutomationRun:
|
||||
"""Fire one scheduled run for ``trigger``.
|
||||
|
||||
Emits calendar context as runtime inputs:
|
||||
|
||||
- ``fired_at`` — actual fire time
|
||||
- ``scheduled_for`` — cron-derived target time for this fire
|
||||
- ``last_fired_at`` — fire time of the previous run, or null on first fire
|
||||
|
||||
The caller (the schedule tick) is responsible for selecting due triggers
|
||||
and advancing ``next_fire_at`` / ``last_fired_at`` before invoking this.
|
||||
"""
|
||||
|
|
@ -33,11 +44,19 @@ async def dispatch_schedule_run(
|
|||
f"automation {trigger.automation_id} is {automation.status.value}, not active"
|
||||
)
|
||||
|
||||
runtime_inputs = {
|
||||
"fired_at": fired_at.isoformat(),
|
||||
"scheduled_for": scheduled_for.isoformat(),
|
||||
"last_fired_at": (
|
||||
previous_last_fired_at.isoformat() if previous_last_fired_at else None
|
||||
),
|
||||
}
|
||||
|
||||
return await dispatch_run(
|
||||
session=session,
|
||||
automation=automation,
|
||||
trigger=trigger,
|
||||
payload=None,
|
||||
runtime_inputs=runtime_inputs,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,10 +5,16 @@ from __future__ import annotations
|
|||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class TriggerDefinition:
|
||||
type: str
|
||||
description: str
|
||||
params_schema: dict[str, Any]
|
||||
payload_schema: dict[str, Any]
|
||||
params_model: type[BaseModel]
|
||||
|
||||
@property
|
||||
def params_schema(self) -> dict[str, Any]:
|
||||
"""JSON Schema (draft 2020-12) derived from ``params_model``."""
|
||||
return self.params_model.model_json_schema()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue