// Copyright (C) 2024 Umorpha Systems // SPDX-License-Identifier: AGPL-3.0-or-later package main import ( "database/sql" "encoding/json" "fmt" _ "github.com/mattn/go-sqlite3" ) type Store struct { db *sql.DB } type JobStatus int const ( StatusNew JobStatus = iota StatusRunning StatusSucceeded StatusFailed StatusError ) type JobID int func OpenStore(filename string) (*Store, error) { db, err := sql.Open("sqlite3", filename) if err != nil { return nil, fmt.Errorf("statedb: open: %w", err) } if _, err := db.Exec(` CREATE TABLE IF NOT EXISTS triggers ( expression TEXT NOT NULL PRIMARY KEY, value TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS jobs ( id INTEGER PRIMARY KEY, trigger_expressions TEXT NOT NULL, -- JSON array of strings trigger_values TEXT NOT NULL, -- JSON array of strings command TEXT NOT NULL, status INTEGER ); `); err != nil { db.Close() return nil, fmt.Errorf("statedb: migrate: %w", err) } return &Store{ db: db, }, nil } func (s *Store) Close() error { return s.db.Close() } func (s *Store) GetTrigger(expr string) (string, error) { var val string err := s.db.QueryRow(`SELECT value FROM triggers WHERE expression = ?`, expr).Scan(&val) if err != nil { return "", fmt.Errorf("statedb: get trigger: %q: %w", expr, err) } return val, nil } func (s *Store) SetTrigger(expr string, val string) error { if _, err := s.db.Exec(`INSERT OR REPLACE INTO triggers(expression, value) VALUES(?, ?)`, expr, val); err != nil { return fmt.Errorf("statedb: set trigger: %q => %q: %w", expr, val, err) } return nil } func (s *Store) NewJob(triggerExprs []string, triggerVals []string, cmd string) (JobID, error) { triggerExprsJSON, err := json.Marshal(triggerExprs) if err != nil { return 0, err } triggerValsJSON, err := json.Marshal(triggerVals) if err != nil { return 0, err } var id JobID if err := s.db.QueryRow(`INSERT INTO jobs(trigger_expressions, trigger_values, command, status) VALUES(?, ?, ?, ?) RETURNING id`, triggerExprsJSON, triggerValsJSON, cmd, StatusNew).Scan(&id); err != nil { return 0, fmt.Errorf("statedb: create job: %w", err) } return id, nil }