panel — open-source game server manager (public release)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 19:19:43 -07:00
commit 5232609719
2160 changed files with 300415 additions and 0 deletions
+139
View File
@@ -0,0 +1,139 @@
package db
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/jackc/pgx/v5"
)
// ScheduleRow is the persisted form of a schedule.
type ScheduleRow struct {
ID string
InstanceID string
Description string
TriggerKind string // "cron" | "event"
CronSpec string // populated for TriggerKind == "cron"
EventSpec string // populated for TriggerKind == "event" — CEL expression returning bool
EventSustainedSeconds int32 // for event: fire only after condition true this many seconds
Action json.RawMessage
Enabled bool
LastFiredAt *time.Time
LastStatus string
LastDetail string
CreatedAt time.Time
UpdatedAt time.Time
}
func (db *DB) InsertSchedule(ctx context.Context, r ScheduleRow) error {
var cronSpec, eventSpec *string
if r.CronSpec != "" {
cronSpec = &r.CronSpec
}
if r.EventSpec != "" {
eventSpec = &r.EventSpec
}
_, err := db.pool.Exec(ctx, `
INSERT INTO schedules (id, instance_id, description, trigger_kind, cron_spec, event_spec, event_sustained_seconds, action, enabled)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
`, r.ID, r.InstanceID, r.Description, r.TriggerKind, cronSpec, eventSpec, r.EventSustainedSeconds, []byte(r.Action), r.Enabled)
if err != nil {
return fmt.Errorf("insert schedule: %w", err)
}
return nil
}
func (db *DB) DeleteSchedule(ctx context.Context, id string) error {
_, err := db.pool.Exec(ctx, `DELETE FROM schedules WHERE id = $1`, id)
if err != nil {
return fmt.Errorf("delete schedule: %w", err)
}
return nil
}
func (db *DB) SetScheduleEnabled(ctx context.Context, id string, enabled bool) error {
_, err := db.pool.Exec(ctx, `UPDATE schedules SET enabled = $2, updated_at = NOW() WHERE id = $1`, id, enabled)
if err != nil {
return fmt.Errorf("set schedule enabled: %w", err)
}
return nil
}
// UpdateSchedule persists changes to an existing schedule row.
func (db *DB) UpdateSchedule(ctx context.Context, r ScheduleRow) error {
_, err := db.pool.Exec(ctx, `
UPDATE schedules
SET description = $2,
trigger_kind = $3,
cron_spec = $4,
event_spec = $5,
event_sustained_seconds = $6,
action = $7,
enabled = $8,
updated_at = NOW()
WHERE id = $1`,
r.ID, r.Description, r.TriggerKind, r.CronSpec, r.EventSpec, r.EventSustainedSeconds, []byte(r.Action), r.Enabled)
if err != nil {
return fmt.Errorf("update schedule: %w", err)
}
return nil
}
// UpdateScheduleFireResult records the outcome of a trigger fire — used by
// the engine to surface success/failure in the UI.
func (db *DB) UpdateScheduleFireResult(ctx context.Context, id, status, detail string) error {
_, err := db.pool.Exec(ctx, `
UPDATE schedules
SET last_fired_at = NOW(), last_status = $2, last_detail = $3, updated_at = NOW()
WHERE id = $1
`, id, status, detail)
if err != nil {
return fmt.Errorf("update schedule result: %w", err)
}
return nil
}
// ListSchedules returns every schedule, optionally filtered by instance_id.
func (db *DB) ListSchedules(ctx context.Context, instanceFilter string) ([]ScheduleRow, error) {
const selectAll = `
SELECT id, instance_id, description, trigger_kind,
COALESCE(cron_spec, ''), COALESCE(event_spec, ''), event_sustained_seconds,
action,
enabled, last_fired_at, COALESCE(last_status, ''), COALESCE(last_detail, ''),
created_at, updated_at
FROM schedules
`
var rows pgx.Rows
var err error
if instanceFilter != "" {
rows, err = db.pool.Query(ctx, selectAll+` WHERE instance_id = $1 ORDER BY id`, instanceFilter)
} else {
rows, err = db.pool.Query(ctx, selectAll+` ORDER BY instance_id, id`)
}
if err != nil {
return nil, fmt.Errorf("list schedules: %w", err)
}
defer rows.Close()
var out []ScheduleRow
for rows.Next() {
var r ScheduleRow
var action []byte
var lastFired *time.Time
if err := rows.Scan(
&r.ID, &r.InstanceID, &r.Description, &r.TriggerKind,
&r.CronSpec, &r.EventSpec, &r.EventSustainedSeconds,
&action,
&r.Enabled, &lastFired, &r.LastStatus, &r.LastDetail,
&r.CreatedAt, &r.UpdatedAt,
); err != nil {
return nil, fmt.Errorf("scan schedule: %w", err)
}
r.Action = action
r.LastFiredAt = lastFired
out = append(out, r)
}
return out, rows.Err()
}