f7a8007af8
Nový DB helper bez ORM: app/db/scheduled_scripts.py
Nové route/UI: app/routes/scheduled_scripts.py
Router registrovaný v app/main.py
Menu doplněné v app/templates/layout.py
Job filtr rozšířený o run_script v app/routes/jobs.py
Implementováno:
GET /portal/scheduled-scripts
GET /portal/scheduled-scripts/{id}
GET/POST /portal/scheduled-scripts/new
GET/POST /portal/scheduled-scripts/{id}/edit
POST /portal/scheduled-scripts/{id}/run-now
POST /portal/scheduled-scripts/{id}/toggle
POST /portal/scheduled-scripts/{id}/delete
Ruční spuštění vytváří run_script job přes existující create_job(...) se source="portal_manual" a payloadem podle zadání. Mazání je blokované, pokud is_running = 1. Validace script_name, schedule_type a timeout_seconds je v route vrstvě.
Audit eventy jsou přidané:
scheduled_script.created
scheduled_script.updated
scheduled_script.deleted
scheduled_script.enabled
scheduled_script.disabled
scheduled_script.run_now
173 lines
4.0 KiB
Python
173 lines
4.0 KiB
Python
from typing import Any
|
|
|
|
from app.db.database import get_connection
|
|
from app.db.migrations import run_migrations
|
|
|
|
|
|
def get_scheduled_scripts():
|
|
run_migrations()
|
|
con = get_connection()
|
|
|
|
rows = con.execute(
|
|
"""
|
|
SELECT
|
|
id,
|
|
name,
|
|
description,
|
|
script_name,
|
|
schedule_type,
|
|
schedule_time,
|
|
timeout_seconds,
|
|
COALESCE(is_enabled, 1) AS is_enabled,
|
|
COALESCE(is_running, 0) AS is_running,
|
|
last_run_at,
|
|
last_status,
|
|
last_job_id,
|
|
last_error_text,
|
|
next_run_at,
|
|
created_at,
|
|
updated_at
|
|
FROM scheduled_scripts
|
|
ORDER BY name
|
|
"""
|
|
).fetchall()
|
|
|
|
con.close()
|
|
return [dict(row) for row in rows]
|
|
|
|
|
|
def get_scheduled_script(script_id: int):
|
|
run_migrations()
|
|
con = get_connection()
|
|
|
|
row = con.execute(
|
|
"""
|
|
SELECT
|
|
id,
|
|
name,
|
|
description,
|
|
script_name,
|
|
schedule_type,
|
|
schedule_time,
|
|
timeout_seconds,
|
|
COALESCE(is_enabled, 1) AS is_enabled,
|
|
COALESCE(is_running, 0) AS is_running,
|
|
last_run_at,
|
|
last_status,
|
|
last_job_id,
|
|
last_error_text,
|
|
next_run_at,
|
|
created_at,
|
|
updated_at
|
|
FROM scheduled_scripts
|
|
WHERE id = ?
|
|
""",
|
|
(script_id,),
|
|
).fetchone()
|
|
|
|
con.close()
|
|
return dict(row) if row else None
|
|
|
|
|
|
def create_scheduled_script(metadata: dict[str, Any]) -> int:
|
|
run_migrations()
|
|
con = get_connection()
|
|
|
|
cur = con.execute(
|
|
"""
|
|
INSERT INTO scheduled_scripts (
|
|
name,
|
|
description,
|
|
script_name,
|
|
schedule_type,
|
|
schedule_time,
|
|
timeout_seconds,
|
|
is_enabled,
|
|
is_running,
|
|
created_at,
|
|
updated_at
|
|
)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, 0, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
|
|
""",
|
|
(
|
|
metadata.get("name"),
|
|
metadata.get("description") or None,
|
|
metadata.get("script_name"),
|
|
metadata.get("schedule_type"),
|
|
metadata.get("schedule_time") or None,
|
|
metadata.get("timeout_seconds"),
|
|
1 if metadata.get("is_enabled") else 0,
|
|
),
|
|
)
|
|
script_id = cur.lastrowid
|
|
con.commit()
|
|
con.close()
|
|
return script_id
|
|
|
|
|
|
def update_scheduled_script(script_id: int, metadata: dict[str, Any]) -> None:
|
|
run_migrations()
|
|
con = get_connection()
|
|
|
|
con.execute(
|
|
"""
|
|
UPDATE scheduled_scripts
|
|
SET name = ?,
|
|
description = ?,
|
|
schedule_type = ?,
|
|
schedule_time = ?,
|
|
timeout_seconds = ?,
|
|
is_enabled = ?,
|
|
updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
""",
|
|
(
|
|
metadata.get("name"),
|
|
metadata.get("description") or None,
|
|
metadata.get("schedule_type"),
|
|
metadata.get("schedule_time") or None,
|
|
metadata.get("timeout_seconds"),
|
|
1 if metadata.get("is_enabled") else 0,
|
|
script_id,
|
|
),
|
|
)
|
|
|
|
con.commit()
|
|
con.close()
|
|
|
|
|
|
def set_scheduled_script_enabled(script_id: int, is_enabled: bool) -> None:
|
|
run_migrations()
|
|
con = get_connection()
|
|
|
|
con.execute(
|
|
"""
|
|
UPDATE scheduled_scripts
|
|
SET is_enabled = ?,
|
|
updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = ?
|
|
""",
|
|
(1 if is_enabled else 0, script_id),
|
|
)
|
|
|
|
con.commit()
|
|
con.close()
|
|
|
|
|
|
def delete_scheduled_script(script_id: int) -> bool:
|
|
run_migrations()
|
|
con = get_connection()
|
|
|
|
cur = con.execute(
|
|
"""
|
|
DELETE FROM scheduled_scripts
|
|
WHERE id = ?
|
|
AND COALESCE(is_running, 0) = 0
|
|
""",
|
|
(script_id,),
|
|
)
|
|
deleted = cur.rowcount == 1
|
|
con.commit()
|
|
con.close()
|
|
return deleted
|