package repository import ( "database/sql" "os" "path/filepath" _ "github.com/mattn/go-sqlite3" ) func NewDB(dbPath string) (*sql.DB, error) { dir := filepath.Dir(dbPath) if err := os.MkdirAll(dir, 0755); err != nil { return nil, err } db, err := sql.Open("sqlite3", dbPath+"?_journal_mode=WAL") if err != nil { return nil, err } if err := initSchema(db); err != nil { db.Close() return nil, err } return db, nil } func initSchema(db *sql.DB) error { schema := ` CREATE TABLE IF NOT EXISTS devices ( id TEXT PRIMARY KEY, hostname TEXT NOT NULL, os TEXT NOT NULL, ip TEXT NOT NULL, registered_at DATETIME NOT NULL, last_report_at DATETIME NOT NULL, status TEXT NOT NULL DEFAULT 'offline' ); CREATE TABLE IF NOT EXISTS metrics ( id INTEGER PRIMARY KEY AUTOINCREMENT, device_id TEXT NOT NULL, timestamp DATETIME NOT NULL, cpu_usage REAL, cpu_temperature REAL, cpu_core_usage TEXT, memory_total INTEGER, memory_used INTEGER, memory_usage REAL, gpu_usage REAL, gpu_temperature REAL, gpu_memory_total INTEGER, gpu_memory_used INTEGER, gpu_name TEXT, network_interfaces TEXT, disks TEXT, power_status TEXT, battery_level INTEGER, power_source TEXT, FOREIGN KEY (device_id) REFERENCES devices(id) ); CREATE INDEX IF NOT EXISTS idx_metrics_device_time ON metrics(device_id, timestamp); CREATE TABLE IF NOT EXISTS alert_rules ( id TEXT PRIMARY KEY, device_id TEXT NOT NULL, metric TEXT NOT NULL, operator TEXT NOT NULL, threshold REAL NOT NULL, duration INTEGER NOT NULL DEFAULT 0, created_at DATETIME NOT NULL, FOREIGN KEY (device_id) REFERENCES devices(id) ); CREATE TABLE IF NOT EXISTS alerts ( id TEXT PRIMARY KEY, device_id TEXT NOT NULL, rule_id TEXT NOT NULL, metric TEXT NOT NULL, value REAL NOT NULL, message TEXT NOT NULL, status TEXT NOT NULL DEFAULT 'active', created_at DATETIME NOT NULL, resolved_at DATETIME, FOREIGN KEY (device_id) REFERENCES devices(id), FOREIGN KEY (rule_id) REFERENCES alert_rules(id) ); ` _, err := db.Exec(schema) return err }