147 lines
4.1 KiB
Go
147 lines
4.1 KiB
Go
package models
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
type Campaign struct {
|
|
ID string `json:"id"`
|
|
RepositoryID string `json:"repository_id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Status string `json:"status"`
|
|
StartedAt time.Time `json:"started_at"`
|
|
FinishedAt *time.Time `json:"finished_at,omitempty"`
|
|
Tags json.RawMessage `json:"tags,omitempty"`
|
|
Metadata json.RawMessage `json:"metadata,omitempty"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
// Joined fields.
|
|
RepoName string `json:"repo_name,omitempty"`
|
|
ArtifactCount int `json:"artifact_count,omitempty"`
|
|
}
|
|
|
|
type CreateCampaignParams struct {
|
|
RepositoryID string
|
|
Name string
|
|
Type string
|
|
Tags json.RawMessage
|
|
Metadata json.RawMessage
|
|
}
|
|
|
|
func CreateCampaign(ctx context.Context, pool *pgxpool.Pool, p CreateCampaignParams) (*Campaign, error) {
|
|
if p.Tags == nil {
|
|
p.Tags = json.RawMessage("{}")
|
|
}
|
|
if p.Metadata == nil {
|
|
p.Metadata = json.RawMessage("{}")
|
|
}
|
|
|
|
c := &Campaign{}
|
|
err := pool.QueryRow(ctx, `
|
|
INSERT INTO campaigns (repository_id, name, type, tags, metadata)
|
|
VALUES ($1, $2, $3, $4, $5)
|
|
RETURNING id, repository_id, name, type, status, started_at, finished_at, tags, metadata, created_at
|
|
`, p.RepositoryID, p.Name, p.Type, p.Tags, p.Metadata).Scan(
|
|
&c.ID, &c.RepositoryID, &c.Name, &c.Type, &c.Status,
|
|
&c.StartedAt, &c.FinishedAt, &c.Tags, &c.Metadata, &c.CreatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("creating campaign: %w", err)
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
func FinishCampaign(ctx context.Context, pool *pgxpool.Pool, id string) error {
|
|
_, err := pool.Exec(ctx, `
|
|
UPDATE campaigns SET status = 'finished', finished_at = NOW() WHERE id = $1
|
|
`, id)
|
|
if err != nil {
|
|
return fmt.Errorf("finishing campaign: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetCampaign(ctx context.Context, pool *pgxpool.Pool, id string) (*Campaign, error) {
|
|
c := &Campaign{}
|
|
err := pool.QueryRow(ctx, `
|
|
SELECT c.id, c.repository_id, c.name, c.type, c.status, c.started_at, c.finished_at,
|
|
c.tags, c.metadata, c.created_at,
|
|
r.name,
|
|
(SELECT COUNT(*) FROM artifacts a WHERE a.campaign_id = c.id)
|
|
FROM campaigns c
|
|
JOIN repositories r ON r.id = c.repository_id
|
|
WHERE c.id = $1
|
|
`, id).Scan(
|
|
&c.ID, &c.RepositoryID, &c.Name, &c.Type, &c.Status,
|
|
&c.StartedAt, &c.FinishedAt, &c.Tags, &c.Metadata, &c.CreatedAt,
|
|
&c.RepoName, &c.ArtifactCount,
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("getting campaign: %w", err)
|
|
}
|
|
return c, nil
|
|
}
|
|
|
|
func ListCampaigns(ctx context.Context, pool *pgxpool.Pool, repoID string, limit, offset int) ([]Campaign, int, error) {
|
|
if limit <= 0 {
|
|
limit = 50
|
|
}
|
|
|
|
baseQuery := `
|
|
FROM campaigns c
|
|
JOIN repositories r ON r.id = c.repository_id
|
|
WHERE 1=1
|
|
`
|
|
args := []any{}
|
|
argN := 1
|
|
|
|
if repoID != "" {
|
|
baseQuery += fmt.Sprintf(" AND c.repository_id = $%d", argN)
|
|
args = append(args, repoID)
|
|
argN++
|
|
}
|
|
|
|
var total int
|
|
err := pool.QueryRow(ctx, "SELECT COUNT(*) "+baseQuery, args...).Scan(&total)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("counting campaigns: %w", err)
|
|
}
|
|
|
|
selectQuery := fmt.Sprintf(`
|
|
SELECT c.id, c.repository_id, c.name, c.type, c.status, c.started_at, c.finished_at,
|
|
c.tags, c.metadata, c.created_at,
|
|
r.name,
|
|
(SELECT COUNT(*) FROM artifacts a WHERE a.campaign_id = c.id)
|
|
%s
|
|
ORDER BY c.created_at DESC
|
|
LIMIT $%d OFFSET $%d
|
|
`, baseQuery, argN, argN+1)
|
|
args = append(args, limit, offset)
|
|
|
|
rows, err := pool.Query(ctx, selectQuery, args...)
|
|
if err != nil {
|
|
return nil, 0, fmt.Errorf("listing campaigns: %w", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
var campaigns []Campaign
|
|
for rows.Next() {
|
|
var c Campaign
|
|
if err := rows.Scan(
|
|
&c.ID, &c.RepositoryID, &c.Name, &c.Type, &c.Status,
|
|
&c.StartedAt, &c.FinishedAt, &c.Tags, &c.Metadata, &c.CreatedAt,
|
|
&c.RepoName, &c.ArtifactCount,
|
|
); err != nil {
|
|
return nil, 0, fmt.Errorf("scanning campaign: %w", err)
|
|
}
|
|
campaigns = append(campaigns, c)
|
|
}
|
|
return campaigns, total, nil
|
|
}
|