95 lines
2.9 KiB
Go
95 lines
2.9 KiB
Go
package downloads
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type Repository struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
func NewRepository(db *sql.DB) *Repository {
|
|
return &Repository{db: db}
|
|
}
|
|
|
|
var ErrNotFound = errors.New("download job not found")
|
|
|
|
func (r *Repository) Create(ctx context.Context, galleryID uuid.UUID, visitorID string) (Job, error) {
|
|
job := Job{ID: uuid.New(), GalleryID: galleryID, VisitorID: visitorID, Status: StatusQueued}
|
|
_, err := r.db.ExecContext(ctx, `
|
|
INSERT INTO download_jobs (id, gallery_id, visitor_id, status)
|
|
VALUES ($1, $2, $3, $4)
|
|
`, job.ID, job.GalleryID, job.VisitorID, job.Status)
|
|
if err != nil {
|
|
return Job{}, fmt.Errorf("create download job: %w", err)
|
|
}
|
|
return r.GetForVisitor(ctx, job.ID, galleryID, visitorID)
|
|
}
|
|
|
|
func (r *Repository) GetForVisitor(ctx context.Context, jobID, galleryID uuid.UUID, visitorID string) (Job, error) {
|
|
return r.get(ctx, `
|
|
WHERE id = $1 AND gallery_id = $2 AND visitor_id = $3
|
|
`, jobID, galleryID, visitorID)
|
|
}
|
|
|
|
func (r *Repository) Get(ctx context.Context, jobID uuid.UUID) (Job, error) {
|
|
return r.get(ctx, `WHERE id = $1`, jobID)
|
|
}
|
|
|
|
func (r *Repository) get(ctx context.Context, predicate string, args ...any) (Job, error) {
|
|
var (
|
|
job Job
|
|
storageKey, jobError, createdAt, updatedAt sql.NullString
|
|
completedAt sql.NullString
|
|
)
|
|
err := r.db.QueryRowContext(ctx, `
|
|
SELECT id, gallery_id, visitor_id, status, storage_key, error, created_at, updated_at, completed_at
|
|
FROM download_jobs
|
|
`+predicate+`
|
|
`, args...).Scan(
|
|
&job.ID, &job.GalleryID, &job.VisitorID, &job.Status, &storageKey, &jobError,
|
|
&createdAt, &updatedAt, &completedAt,
|
|
)
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
return Job{}, ErrNotFound
|
|
}
|
|
if err != nil {
|
|
return Job{}, fmt.Errorf("find download job: %w", err)
|
|
}
|
|
job.StorageKey = storageKey.String
|
|
job.Error = jobError.String
|
|
job.CreatedAt = createdAt.String
|
|
job.UpdatedAt = updatedAt.String
|
|
job.CompletedAt = completedAt.String
|
|
return job, nil
|
|
}
|
|
|
|
func (r *Repository) MarkProcessing(ctx context.Context, jobID uuid.UUID) error {
|
|
_, err := r.db.ExecContext(ctx, `
|
|
UPDATE download_jobs SET status = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2
|
|
`, StatusProcessing, jobID)
|
|
return err
|
|
}
|
|
|
|
func (r *Repository) MarkReady(ctx context.Context, jobID uuid.UUID, storageKey string) error {
|
|
_, err := r.db.ExecContext(ctx, `
|
|
UPDATE download_jobs SET status = $1, storage_key = $2, error = NULL,
|
|
updated_at = CURRENT_TIMESTAMP, completed_at = CURRENT_TIMESTAMP
|
|
WHERE id = $3
|
|
`, StatusReady, storageKey, jobID)
|
|
return err
|
|
}
|
|
|
|
func (r *Repository) MarkFailed(ctx context.Context, jobID uuid.UUID, message string) error {
|
|
_, err := r.db.ExecContext(ctx, `
|
|
UPDATE download_jobs SET status = $1, error = $2, updated_at = CURRENT_TIMESTAMP
|
|
WHERE id = $3
|
|
`, StatusFailed, message, jobID)
|
|
return err
|
|
}
|