cairn/internal/models/campaign.go

126 lines
3.3 KiB
Go

package models
import (
"context"
"encoding/json"
"fmt"
"time"
cairnapi "github.com/mattnite/cairn/internal/api"
"gorm.io/gorm"
)
type CreateCampaignParams struct {
RepositoryID uint
Name string
Type string
Tags json.RawMessage
Metadata json.RawMessage
}
func CreateCampaign(ctx context.Context, db *gorm.DB, p CreateCampaignParams) (*cairnapi.Campaign, error) {
if p.Tags == nil {
p.Tags = json.RawMessage("{}")
}
if p.Metadata == nil {
p.Metadata = json.RawMessage("{}")
}
campaign := &Campaign{
RepositoryID: p.RepositoryID,
Name: p.Name,
Type: p.Type,
Status: "running",
StartedAt: time.Now(),
Tags: p.Tags,
Metadata: p.Metadata,
}
if err := db.WithContext(ctx).Create(campaign).Error; err != nil {
return nil, fmt.Errorf("creating campaign: %w", err)
}
return enrichCampaign(ctx, db, *campaign)
}
func FinishCampaign(ctx context.Context, db *gorm.DB, id uint) error {
now := time.Now()
if err := db.WithContext(ctx).Model(&Campaign{}).Where("id = ?", id).Updates(map[string]any{
"status": "finished",
"finished_at": now,
}).Error; err != nil {
return fmt.Errorf("finishing campaign: %w", err)
}
return nil
}
func GetCampaign(ctx context.Context, db *gorm.DB, id uint) (*cairnapi.Campaign, error) {
campaign := &Campaign{}
if err := db.WithContext(ctx).First(campaign, id).Error; err != nil {
return nil, fmt.Errorf("getting campaign: %w", err)
}
return enrichCampaign(ctx, db, *campaign)
}
func ListCampaigns(ctx context.Context, db *gorm.DB, repoID *uint, limit, offset int) ([]cairnapi.Campaign, int64, error) {
if limit <= 0 {
limit = 50
}
query := db.WithContext(ctx).Model(&Campaign{})
if repoID != nil {
query = query.Where("repository_id = ?", *repoID)
}
var total int64
if err := query.Count(&total).Error; err != nil {
return nil, 0, fmt.Errorf("counting campaigns: %w", err)
}
var dbCampaigns []Campaign
if err := query.Order("created_at DESC").Limit(limit).Offset(offset).Find(&dbCampaigns).Error; err != nil {
return nil, 0, fmt.Errorf("listing campaigns: %w", err)
}
campaigns := make([]cairnapi.Campaign, 0, len(dbCampaigns))
for _, m := range dbCampaigns {
c, err := enrichCampaign(ctx, db, m)
if err != nil {
return nil, 0, err
}
campaigns = append(campaigns, *c)
}
return campaigns, total, nil
}
func enrichCampaign(ctx context.Context, db *gorm.DB, model Campaign) (*cairnapi.Campaign, error) {
repo := &Repository{}
if err := db.WithContext(ctx).First(repo, model.RepositoryID).Error; err != nil {
return nil, fmt.Errorf("loading campaign repository: %w", err)
}
var count int64
if err := db.WithContext(ctx).Model(&Artifact{}).Where("campaign_id = ?", model.ID).Count(&count).Error; err != nil {
return nil, fmt.Errorf("counting campaign artifacts: %w", err)
}
campaign := campaignFromModel(model)
campaign.RepoName = repo.Name
campaign.ArtifactCount = count
return &campaign, nil
}
func campaignFromModel(m Campaign) cairnapi.Campaign {
return cairnapi.Campaign{
ID: m.ID,
RepositoryID: m.RepositoryID,
Name: m.Name,
Type: m.Type,
Status: m.Status,
StartedAt: m.StartedAt,
FinishedAt: m.FinishedAt,
Tags: m.Tags,
Metadata: m.Metadata,
CreatedAt: m.CreatedAt,
}
}