Files
sub2api-cn-relay-manager/internal/store/sqlite/import_runs_repo.go

164 lines
5.9 KiB
Go

package sqlite
import (
"context"
"fmt"
"strings"
)
type ImportRun struct {
RunID string
HostID string
Mode string
AccessMode string
SubscriptionUsersJSON string
SubscriptionDays int
ProbeAPIKey string
State string
TotalItems int
CompletedItems int
ActiveItems int
DegradedItems int
BrokenItems int
WarningItems int
StartedAt string
UpdatedAt string
FinishedAt string
}
type ImportRunsRepo struct {
db execQuerier
}
func newImportRunsRepo(db execQuerier) *ImportRunsRepo {
return &ImportRunsRepo{db: db}
}
func (r *ImportRunsRepo) Create(ctx context.Context, run ImportRun) error {
runID := strings.TrimSpace(run.RunID)
hostID := strings.TrimSpace(run.HostID)
mode := strings.TrimSpace(run.Mode)
accessMode := strings.TrimSpace(run.AccessMode)
subscriptionUsersJSON := defaultJSON(run.SubscriptionUsersJSON, "[]")
probeAPIKey := strings.TrimSpace(run.ProbeAPIKey)
state := strings.TrimSpace(run.State)
switch {
case runID == "":
return fmt.Errorf("run_id is required")
case hostID == "":
return fmt.Errorf("host_id is required")
case mode == "":
return fmt.Errorf("mode is required")
case accessMode == "":
return fmt.Errorf("access_mode is required")
case state == "":
return fmt.Errorf("state is required")
}
if _, err := r.db.ExecContext(ctx, `INSERT INTO import_runs (run_id, host_id, mode, access_mode, subscription_users_json, subscription_days, probe_api_key, state, total_items, completed_items, active_items, degraded_items, broken_items, warning_items) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
runID, hostID, mode, accessMode, subscriptionUsersJSON, run.SubscriptionDays, probeAPIKey, state, run.TotalItems, run.CompletedItems, run.ActiveItems, run.DegradedItems, run.BrokenItems, run.WarningItems); err != nil {
return fmt.Errorf("insert import run %q: %w", runID, err)
}
return nil
}
func (r *ImportRunsRepo) Update(ctx context.Context, run ImportRun) error {
runID := strings.TrimSpace(run.RunID)
hostID := strings.TrimSpace(run.HostID)
mode := strings.TrimSpace(run.Mode)
accessMode := strings.TrimSpace(run.AccessMode)
subscriptionUsersJSON := defaultJSON(run.SubscriptionUsersJSON, "[]")
probeAPIKey := strings.TrimSpace(run.ProbeAPIKey)
state := strings.TrimSpace(run.State)
finishedAt := strings.TrimSpace(run.FinishedAt)
switch {
case runID == "":
return fmt.Errorf("run_id is required")
case hostID == "":
return fmt.Errorf("host_id is required")
case mode == "":
return fmt.Errorf("mode is required")
case accessMode == "":
return fmt.Errorf("access_mode is required")
case state == "":
return fmt.Errorf("state is required")
}
if _, err := r.db.ExecContext(ctx, `UPDATE import_runs
SET host_id = ?, mode = ?, access_mode = ?, subscription_users_json = ?, subscription_days = ?, probe_api_key = ?, state = ?, total_items = ?, completed_items = ?, active_items = ?, degraded_items = ?, broken_items = ?, warning_items = ?, finished_at = ?, updated_at = CURRENT_TIMESTAMP
WHERE run_id = ?`,
hostID, mode, accessMode, subscriptionUsersJSON, run.SubscriptionDays, probeAPIKey, state, run.TotalItems, run.CompletedItems, run.ActiveItems, run.DegradedItems, run.BrokenItems, run.WarningItems, nullableString(finishedAt), runID); err != nil {
return fmt.Errorf("update import run %q: %w", runID, err)
}
return nil
}
func (r *ImportRunsRepo) GetByRunID(ctx context.Context, runID string) (ImportRun, error) {
runID = strings.TrimSpace(runID)
if runID == "" {
return ImportRun{}, fmt.Errorf("run_id is required")
}
var run ImportRun
if err := r.db.QueryRowContext(ctx, `SELECT run_id, host_id, mode, access_mode, subscription_users_json, subscription_days, COALESCE(probe_api_key, ''), state, total_items, completed_items, active_items, degraded_items, broken_items, warning_items, started_at, updated_at, COALESCE(finished_at, '') FROM import_runs WHERE run_id = ?`, runID).
Scan(&run.RunID, &run.HostID, &run.Mode, &run.AccessMode, &run.SubscriptionUsersJSON, &run.SubscriptionDays, &run.ProbeAPIKey, &run.State, &run.TotalItems, &run.CompletedItems, &run.ActiveItems, &run.DegradedItems, &run.BrokenItems, &run.WarningItems, &run.StartedAt, &run.UpdatedAt, &run.FinishedAt); err != nil {
return ImportRun{}, err
}
return run, nil
}
func (r *ImportRunsRepo) List(ctx context.Context, limit int) ([]ImportRun, error) {
if limit <= 0 {
limit = 50
}
rows, err := r.db.QueryContext(ctx, `SELECT run_id, host_id, mode, access_mode, subscription_users_json, subscription_days, COALESCE(probe_api_key, ''), state, total_items, completed_items, active_items, degraded_items, broken_items, warning_items, started_at, updated_at, COALESCE(finished_at, '') FROM import_runs ORDER BY started_at DESC LIMIT ?`, limit)
if err != nil {
return nil, fmt.Errorf("list import runs: %w", err)
}
defer rows.Close()
runs := make([]ImportRun, 0)
for rows.Next() {
var run ImportRun
if err := rows.Scan(&run.RunID, &run.HostID, &run.Mode, &run.AccessMode, &run.SubscriptionUsersJSON, &run.SubscriptionDays, &run.ProbeAPIKey, &run.State, &run.TotalItems, &run.CompletedItems, &run.ActiveItems, &run.DegradedItems, &run.BrokenItems, &run.WarningItems, &run.StartedAt, &run.UpdatedAt, &run.FinishedAt); err != nil {
return nil, fmt.Errorf("scan import run: %w", err)
}
runs = append(runs, run)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate import runs: %w", err)
}
return runs, nil
}
type sqlNullInt64 struct {
Int64 int64
Valid bool
}
func (n sqlNullInt64) ptr() *int64 {
if !n.Valid {
return nil
}
value := n.Int64
return &value
}
func nullableString(value string) any {
if strings.TrimSpace(value) == "" {
return nil
}
return value
}
func defaultJSON(value, fallback string) string {
value = strings.TrimSpace(value)
if value == "" {
return fallback
}
return value
}