clonepack/internal/store/clone_job.go
GnomeZworc 274ea454dd
first with full handle over rpm
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
2026-04-25 14:50:08 +02:00

109 lines
3.2 KiB
Go

package store
import (
"context"
"database/sql"
"errors"
"time"
)
type CloneJobStatus string
const (
CloneJobPending CloneJobStatus = "pending"
CloneJobRunning CloneJobStatus = "running"
CloneJobCompleted CloneJobStatus = "completed"
CloneJobFailed CloneJobStatus = "failed"
)
type CloneJob struct {
ID int64
RepoID int64
Status CloneJobStatus
StartedAt *time.Time
FinishedAt *time.Time
Error *string
CreatedAt time.Time
}
type CloneJobStore interface {
CreateCloneJob(ctx context.Context, repoID int64) (int64, error)
GetCloneJob(ctx context.Context, id int64) (*CloneJob, error)
GetLatestCloneJob(ctx context.Context, repoID int64) (*CloneJob, error)
HasRunningCloneJob(ctx context.Context, repoID int64) (bool, error)
MarkCloneJobStarted(ctx context.Context, id int64) error
MarkCloneJobFinished(ctx context.Context, id int64, status CloneJobStatus, errMsg *string) error
}
type SQLiteCloneJobStore struct {
db *sql.DB
}
func NewCloneJobStore(db *sql.DB) *SQLiteCloneJobStore {
return &SQLiteCloneJobStore{db: db}
}
func (s *SQLiteCloneJobStore) CreateCloneJob(ctx context.Context, repoID int64) (int64, error) {
res, err := s.db.ExecContext(ctx, `INSERT INTO clone_jobs (repo_id) VALUES (?)`, repoID)
if err != nil {
return 0, err
}
return res.LastInsertId()
}
func (s *SQLiteCloneJobStore) GetCloneJob(ctx context.Context, id int64) (*CloneJob, error) {
row := s.db.QueryRowContext(ctx,
`SELECT id, repo_id, status, started_at, finished_at, error, created_at FROM clone_jobs WHERE id = ?`, id)
return scanCloneJob(row)
}
func (s *SQLiteCloneJobStore) GetLatestCloneJob(ctx context.Context, repoID int64) (*CloneJob, error) {
row := s.db.QueryRowContext(ctx,
`SELECT id, repo_id, status, started_at, finished_at, error, created_at FROM clone_jobs WHERE repo_id = ? ORDER BY created_at DESC LIMIT 1`, repoID)
return scanCloneJob(row)
}
func (s *SQLiteCloneJobStore) HasRunningCloneJob(ctx context.Context, repoID int64) (bool, error) {
var count int
err := s.db.QueryRowContext(ctx,
`SELECT COUNT(*) FROM clone_jobs WHERE repo_id = ? AND status IN ('pending','running')`, repoID,
).Scan(&count)
return count > 0, err
}
func (s *SQLiteCloneJobStore) MarkCloneJobStarted(ctx context.Context, id int64) error {
_, err := s.db.ExecContext(ctx,
`UPDATE clone_jobs SET status='running', started_at=CURRENT_TIMESTAMP WHERE id=?`, id)
return err
}
func (s *SQLiteCloneJobStore) MarkCloneJobFinished(ctx context.Context, id int64, status CloneJobStatus, errMsg *string) error {
_, err := s.db.ExecContext(ctx,
`UPDATE clone_jobs SET status=?, finished_at=CURRENT_TIMESTAMP, error=? WHERE id=?`,
status, errMsg, id)
return err
}
func scanCloneJob(row *sql.Row) (*CloneJob, error) {
var j CloneJob
var startedAt, finishedAt sql.NullTime
var errMsg sql.NullString
err := row.Scan(&j.ID, &j.RepoID, &j.Status, &startedAt, &finishedAt, &errMsg, &j.CreatedAt)
if errors.Is(err, sql.ErrNoRows) {
return nil, ErrNotFound
}
if err != nil {
return nil, err
}
if startedAt.Valid {
j.StartedAt = &startedAt.Time
}
if finishedAt.Valid {
j.FinishedAt = &finishedAt.Time
}
if errMsg.Valid {
j.Error = &errMsg.String
}
return &j, nil
}