update check active
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
from collections.abc import Iterator
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
from app.config import settings
|
||||
@@ -55,6 +57,8 @@ CREATE TABLE IF NOT EXISTS installed_components (
|
||||
package_name TEXT,
|
||||
package_version TEXT,
|
||||
service_name TEXT,
|
||||
service_check_status TEXT DEFAULT 'not-checked',
|
||||
service_checks_json TEXT,
|
||||
docker_image TEXT,
|
||||
docker_digest TEXT,
|
||||
container_name TEXT,
|
||||
@@ -75,6 +79,8 @@ CREATE TABLE IF NOT EXISTS task_components (
|
||||
progress INTEGER DEFAULT 0,
|
||||
current_step TEXT,
|
||||
error_message TEXT,
|
||||
service_check_status TEXT DEFAULT 'not-checked',
|
||||
service_checks_json TEXT,
|
||||
started_at TEXT,
|
||||
finished_at TEXT,
|
||||
FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE
|
||||
@@ -96,10 +102,18 @@ def _ensure_column(connection: sqlite3.Connection, table: str, column: str, defi
|
||||
connection.execute(f"ALTER TABLE {table} ADD COLUMN {column} {definition}")
|
||||
|
||||
|
||||
def get_connection() -> sqlite3.Connection:
|
||||
@contextmanager
|
||||
def get_connection() -> Iterator[sqlite3.Connection]:
|
||||
connection = sqlite3.connect(settings.db_path, timeout=30)
|
||||
connection.row_factory = sqlite3.Row
|
||||
return connection
|
||||
try:
|
||||
yield connection
|
||||
connection.commit()
|
||||
except Exception:
|
||||
connection.rollback()
|
||||
raise
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
|
||||
def initialize_database() -> None:
|
||||
@@ -110,3 +124,17 @@ def initialize_database() -> None:
|
||||
with get_connection() as connection:
|
||||
connection.executescript(SCHEMA)
|
||||
_ensure_column(connection, "installed_apps", "open_url", "TEXT")
|
||||
_ensure_column(
|
||||
connection,
|
||||
"installed_components",
|
||||
"service_check_status",
|
||||
"TEXT DEFAULT 'not-checked'",
|
||||
)
|
||||
_ensure_column(connection, "installed_components", "service_checks_json", "TEXT")
|
||||
_ensure_column(
|
||||
connection,
|
||||
"task_components",
|
||||
"service_check_status",
|
||||
"TEXT DEFAULT 'not-checked'",
|
||||
)
|
||||
_ensure_column(connection, "task_components", "service_checks_json", "TEXT")
|
||||
|
||||
@@ -17,6 +17,29 @@ def row_to_dict(row: Any) -> dict[str, Any] | None:
|
||||
return dict(row)
|
||||
|
||||
|
||||
def _encode_service_checks(value: list[dict[str, Any]]) -> str:
|
||||
return json.dumps(value, ensure_ascii=False, separators=(",", ":"))
|
||||
|
||||
|
||||
def _decode_service_checks(value: Any) -> list[dict[str, Any]]:
|
||||
if not value:
|
||||
return []
|
||||
try:
|
||||
decoded = json.loads(str(value))
|
||||
except (TypeError, ValueError, json.JSONDecodeError):
|
||||
return []
|
||||
if not isinstance(decoded, list):
|
||||
return []
|
||||
return [item for item in decoded if isinstance(item, dict)]
|
||||
|
||||
|
||||
def _component_row(row: Any) -> dict[str, Any]:
|
||||
item = dict(row)
|
||||
item["service_checks"] = _decode_service_checks(item.pop("service_checks_json", None))
|
||||
item["service_check_status"] = item.get("service_check_status") or "not-checked"
|
||||
return item
|
||||
|
||||
|
||||
class Repository:
|
||||
def create_task(self, task_id: str, task_type: str, app_id: str, app_name: str | None) -> None:
|
||||
now = utc_now()
|
||||
@@ -118,6 +141,8 @@ class Repository:
|
||||
progress: int | None = None,
|
||||
current_step: str | None = None,
|
||||
error_message: str | None = None,
|
||||
service_check_status: str | None = None,
|
||||
service_checks: list[dict[str, Any]] | None = None,
|
||||
started_at: str | None = None,
|
||||
finished_at: str | None = None,
|
||||
) -> None:
|
||||
@@ -128,6 +153,12 @@ class Repository:
|
||||
"progress": progress,
|
||||
"current_step": current_step,
|
||||
"error_message": error_message,
|
||||
"service_check_status": service_check_status,
|
||||
"service_checks_json": (
|
||||
_encode_service_checks(service_checks)
|
||||
if service_checks is not None
|
||||
else None
|
||||
),
|
||||
"started_at": started_at,
|
||||
"finished_at": finished_at,
|
||||
}.items():
|
||||
@@ -147,14 +178,15 @@ class Repository:
|
||||
with get_connection() as connection:
|
||||
rows = connection.execute(
|
||||
"""
|
||||
SELECT component_id, type, status, progress, current_step, error_message, started_at, finished_at
|
||||
SELECT component_id, type, status, progress, current_step, error_message,
|
||||
service_check_status, service_checks_json, started_at, finished_at
|
||||
FROM task_components
|
||||
WHERE task_id = ?
|
||||
ORDER BY install_order ASC, id ASC
|
||||
""",
|
||||
(task_id,),
|
||||
).fetchall()
|
||||
return [dict(row) for row in rows]
|
||||
return [_component_row(row) for row in rows]
|
||||
|
||||
def list_installed_apps(self) -> list[dict[str, Any]]:
|
||||
with get_connection() as connection:
|
||||
@@ -205,10 +237,11 @@ class Repository:
|
||||
"""
|
||||
INSERT INTO installed_components (
|
||||
app_id, component_id, type, install_order, status, package_name, package_version,
|
||||
service_name, docker_image, docker_digest, container_name, compose_project_name,
|
||||
service_name, service_check_status, service_checks_json,
|
||||
docker_image, docker_digest, container_name, compose_project_name,
|
||||
installed_at, updated_at
|
||||
)
|
||||
VALUES (?, ?, ?, ?, 'installed', ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, 'installed', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(app_id, component_id) DO UPDATE SET
|
||||
type = excluded.type,
|
||||
install_order = excluded.install_order,
|
||||
@@ -216,6 +249,8 @@ class Repository:
|
||||
package_name = excluded.package_name,
|
||||
package_version = excluded.package_version,
|
||||
service_name = excluded.service_name,
|
||||
service_check_status = excluded.service_check_status,
|
||||
service_checks_json = excluded.service_checks_json,
|
||||
docker_image = excluded.docker_image,
|
||||
docker_digest = excluded.docker_digest,
|
||||
container_name = excluded.container_name,
|
||||
@@ -230,6 +265,8 @@ class Repository:
|
||||
component.get("packageName"),
|
||||
component.get("version"),
|
||||
component.get("serviceName"),
|
||||
component.get("serviceCheckStatus", "not-checked"),
|
||||
_encode_service_checks(component.get("serviceChecks", [])),
|
||||
component.get("image"),
|
||||
component.get("digest"),
|
||||
component.get("containerName"),
|
||||
@@ -250,7 +287,7 @@ class Repository:
|
||||
""",
|
||||
(app_id,),
|
||||
).fetchall()
|
||||
return [dict(row) for row in rows]
|
||||
return [_component_row(row) for row in rows]
|
||||
|
||||
def export_manifest_hash(self, manifest: dict[str, Any]) -> str:
|
||||
return json.dumps(manifest, sort_keys=True, separators=(",", ":"))
|
||||
|
||||
Reference in New Issue
Block a user