panel v0.9.2 — open-source game server manager
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
// UpdateCheckRow is the persisted result of the last update-available
|
||||
// check for an instance (WI-14). CHECK-ONLY bookkeeping.
|
||||
type UpdateCheckRow struct {
|
||||
InstanceID string
|
||||
AppID string
|
||||
Branch string
|
||||
InstalledBuildID string
|
||||
LatestBuildID string
|
||||
UpdateAvailable bool
|
||||
Error string
|
||||
CheckedAt time.Time
|
||||
}
|
||||
|
||||
// UpsertUpdateCheck records the latest check result for an instance.
|
||||
func (db *DB) UpsertUpdateCheck(ctx context.Context, r UpdateCheckRow) error {
|
||||
_, err := db.pool.Exec(ctx, `
|
||||
INSERT INTO update_checks (instance_id, app_id, branch, installed_buildid, latest_buildid, update_available, error, checked_at)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW())
|
||||
ON CONFLICT (instance_id) DO UPDATE SET
|
||||
app_id = EXCLUDED.app_id,
|
||||
branch = EXCLUDED.branch,
|
||||
installed_buildid = EXCLUDED.installed_buildid,
|
||||
latest_buildid = EXCLUDED.latest_buildid,
|
||||
update_available = EXCLUDED.update_available,
|
||||
error = EXCLUDED.error,
|
||||
checked_at = NOW()
|
||||
`, r.InstanceID, r.AppID, r.Branch, r.InstalledBuildID, r.LatestBuildID, r.UpdateAvailable, r.Error)
|
||||
if err != nil {
|
||||
return fmt.Errorf("upsert update check: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUpdateCheck returns the last stored check for an instance, or
|
||||
// (nil, nil) when the instance has never been checked.
|
||||
func (db *DB) GetUpdateCheck(ctx context.Context, instanceID string) (*UpdateCheckRow, error) {
|
||||
row := db.pool.QueryRow(ctx, `
|
||||
SELECT instance_id, app_id, branch, installed_buildid, latest_buildid, update_available, error, checked_at
|
||||
FROM update_checks WHERE instance_id = $1
|
||||
`, instanceID)
|
||||
var r UpdateCheckRow
|
||||
err := row.Scan(&r.InstanceID, &r.AppID, &r.Branch, &r.InstalledBuildID, &r.LatestBuildID, &r.UpdateAvailable, &r.Error, &r.CheckedAt)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get update check: %w", err)
|
||||
}
|
||||
return &r, nil
|
||||
}
|
||||
|
||||
// ListUpdateChecks returns every stored check, keyed for the dashboard's
|
||||
// "Update available" badges.
|
||||
func (db *DB) ListUpdateChecks(ctx context.Context) ([]UpdateCheckRow, error) {
|
||||
rows, err := db.pool.Query(ctx, `
|
||||
SELECT instance_id, app_id, branch, installed_buildid, latest_buildid, update_available, error, checked_at
|
||||
FROM update_checks ORDER BY instance_id
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list update checks: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []UpdateCheckRow
|
||||
for rows.Next() {
|
||||
var r UpdateCheckRow
|
||||
if err := rows.Scan(&r.InstanceID, &r.AppID, &r.Branch, &r.InstalledBuildID, &r.LatestBuildID, &r.UpdateAvailable, &r.Error, &r.CheckedAt); err != nil {
|
||||
return nil, fmt.Errorf("scan update check: %w", err)
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// DeleteUpdateCheck removes an instance's row (instance deleted).
|
||||
func (db *DB) DeleteUpdateCheck(ctx context.Context, instanceID string) error {
|
||||
_, err := db.pool.Exec(ctx, `DELETE FROM update_checks WHERE instance_id = $1`, instanceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete update check: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user