- Implemented HTML pages for datasets, models, training, testing, and results. - Created API endpoints for managing repositories, results, tests, and training sessions. - Added functionality for streaming training progress via Server-Sent Events (SSE). - Introduced a Dockerfile for the ML runner with necessary dependencies. - Developed an SDK for user code execution within the runner container. - Enhanced CSS styles for improved UI layout and navigation. - Established a layout template for consistent HTML structure across pages. - Added JavaScript for dynamic interactions on the models page. - Implemented WebSocket handling for real-time communication with kiosk devices and controllers. - Implemented model registration and management API at /api/models - Added Gitea proxy API for repository interactions at /api/repos - Created results API for listing and comparing training results at /api/results - Developed training management API for enqueueing and retrieving training jobs at /api/trainings - Introduced SSE endpoint for live training progress updates - Added HTML pages for models, datasets, and training management - Created a Dockerfile for the ML runner with necessary dependencies - Developed SDK for user code execution within the runner container - Enhanced CSS styles for improved UI/UX - Implemented WebSocket communication for real-time device and controller interactions in the kiosk system
125 lines
6.0 KiB
PL/PgSQL
125 lines
6.0 KiB
PL/PgSQL
-- ============================================================
|
|
-- Rulesets schema (DB: rules)
|
|
-- ------------------------------------------------------------
|
|
-- Un ruleset e' una collezione versionata di "items" (paths
|
|
-- Signal K per i logs, codici openmeteo per i forecasts, ...).
|
|
-- Modello:
|
|
-- * 5 tipi fissi: logs | forecast_current | forecast_hourly
|
|
-- | marine_current | marine_hourly
|
|
-- * Un solo ruleset puo' essere "active" per ciascun tipo.
|
|
-- * Le versioni sono triple di interi 1..100 (major.build.patch).
|
|
-- * Gli items sono JSONB per massima flessibilita'.
|
|
-- * Ogni item ha un "ref" stabile scelto dall'utente: e' la
|
|
-- chiave logica che garantisce continuita' su InfluxDB anche
|
|
-- se il path del sensore cambia.
|
|
-- * Le deployments tracciano quale ruleset-version e' stato
|
|
-- pushato ad ogni sensore.
|
|
-- ============================================================
|
|
|
|
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
|
|
-- ─────────────────────────────────────────────────────────────
|
|
-- RULESETS
|
|
-- ─────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS rulesets (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
type TEXT NOT NULL
|
|
CHECK (type IN ('logs','forecast_current','forecast_hourly','marine_current','marine_hourly')),
|
|
version_major SMALLINT NOT NULL DEFAULT 1 CHECK (version_major BETWEEN 1 AND 100),
|
|
version_build SMALLINT NOT NULL DEFAULT 0 CHECK (version_build BETWEEN 0 AND 100),
|
|
version_patch SMALLINT NOT NULL DEFAULT 0 CHECK (version_patch BETWEEN 0 AND 100),
|
|
description TEXT NOT NULL DEFAULT '',
|
|
tags TEXT[] NOT NULL DEFAULT '{}',
|
|
-- items: [{ ref, path, enabled, meta: {...} }, ...]
|
|
-- ref: identificatore logico stabile (chiave su Influx)
|
|
-- path: SK path (logs) | codice openmeteo (forecast/marine)
|
|
-- meta: { name, unit, measurement, sk_path, group_name, category, ... }
|
|
items JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
active BOOLEAN NOT NULL DEFAULT false,
|
|
archived BOOLEAN NOT NULL DEFAULT false,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
UNIQUE (type, version_major, version_build, version_patch)
|
|
);
|
|
|
|
-- solo UN ruleset active per tipo (archiviati esclusi)
|
|
CREATE UNIQUE INDEX IF NOT EXISTS rulesets_one_active_per_type
|
|
ON rulesets (type)
|
|
WHERE active = true AND archived = false;
|
|
|
|
CREATE INDEX IF NOT EXISTS rulesets_type_idx ON rulesets (type);
|
|
CREATE INDEX IF NOT EXISTS rulesets_active_idx ON rulesets (type) WHERE active = true;
|
|
CREATE INDEX IF NOT EXISTS rulesets_archived_idx ON rulesets (archived);
|
|
CREATE INDEX IF NOT EXISTS rulesets_items_gin_idx ON rulesets USING GIN (items);
|
|
|
|
-- Validazione items: array di oggetti con almeno ref+path
|
|
CREATE OR REPLACE FUNCTION rulesets_validate_items() RETURNS trigger AS $$
|
|
DECLARE
|
|
refs TEXT[];
|
|
BEGIN
|
|
IF jsonb_typeof(NEW.items) <> 'array' THEN
|
|
RAISE EXCEPTION 'items must be a JSON array';
|
|
END IF;
|
|
|
|
-- tutti gli item devono avere ref non vuoto e path (anche vuoto ammesso)
|
|
IF EXISTS (
|
|
SELECT 1 FROM jsonb_array_elements(NEW.items) it
|
|
WHERE jsonb_typeof(it) <> 'object'
|
|
OR NULLIF(it->>'ref','') IS NULL
|
|
) THEN
|
|
RAISE EXCEPTION 'every item must be an object with a non-empty "ref"';
|
|
END IF;
|
|
|
|
-- unicita' ref all'interno dello stesso ruleset
|
|
SELECT array_agg(it->>'ref') INTO refs
|
|
FROM jsonb_array_elements(NEW.items) it;
|
|
IF (SELECT count(DISTINCT x) FROM unnest(refs) x) <> COALESCE(array_length(refs,1),0) THEN
|
|
RAISE EXCEPTION 'item refs must be unique within the ruleset';
|
|
END IF;
|
|
|
|
NEW.updated_at := NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS rulesets_validate_trigger ON rulesets;
|
|
CREATE TRIGGER rulesets_validate_trigger
|
|
BEFORE INSERT OR UPDATE ON rulesets
|
|
FOR EACH ROW EXECUTE FUNCTION rulesets_validate_items();
|
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────
|
|
-- DEPLOYMENTS
|
|
-- Traccia quale ruleset-version e' stato pushato ad ogni
|
|
-- sensore (per tipo). Un solo ruleset per (sensor,type).
|
|
-- ─────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS ruleset_deployments (
|
|
sensor_name TEXT NOT NULL,
|
|
type TEXT NOT NULL,
|
|
ruleset_id UUID NOT NULL REFERENCES rulesets(id) ON DELETE CASCADE,
|
|
deployed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
acked_at TIMESTAMPTZ,
|
|
PRIMARY KEY (sensor_name, type)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ruleset_deployments_ruleset_idx
|
|
ON ruleset_deployments (ruleset_id);
|
|
|
|
|
|
-- ─────────────────────────────────────────────────────────────
|
|
-- AUDIT LOG (opzionale ma utile)
|
|
-- ─────────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS ruleset_changes (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
ruleset_id UUID,
|
|
type TEXT,
|
|
action TEXT NOT NULL, -- created | updated | activated | archived | deleted | deployed
|
|
user_id TEXT,
|
|
payload JSONB,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS ruleset_changes_ruleset_idx ON ruleset_changes (ruleset_id);
|
|
CREATE INDEX IF NOT EXISTS ruleset_changes_created_idx ON ruleset_changes (created_at DESC);
|