Files
2026-06-22 08:55:57 +08:00

128 lines
3.1 KiB
Go

package docs
import (
"context"
"errors"
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
"github.com/jackc/pgx/v5/pgxpool"
docssqlc "github.com/yan1h/agent-coding-workflow/internal/docs/sqlc"
"github.com/yan1h/agent-coding-workflow/internal/infra/errs"
)
// Repository is the docs persistence contract.
type Repository interface {
Get(ctx context.Context, wsID uuid.UUID, commitSHA, kind string) (*Summary, error)
Upsert(ctx context.Context, in UpsertInput) (*Summary, error)
}
// UpsertInput carries the fields for a commit_summaries upsert.
type UpsertInput struct {
WorkspaceID uuid.UUID
WorktreeID *uuid.UUID
Branch string
CommitSHA string
Kind string
Title *string
BodyMD string
Model *string
Status string
Error *string
}
// PgRepository is the production Repository on a pgxpool.Pool.
type PgRepository struct {
pool *pgxpool.Pool
q *docssqlc.Queries
}
// NewPostgresRepository builds a PgRepository.
func NewPostgresRepository(pool *pgxpool.Pool) *PgRepository {
return &PgRepository{pool: pool, q: docssqlc.New(pool)}
}
var _ Repository = (*PgRepository)(nil)
func pgUUID(u uuid.UUID) pgtype.UUID { return pgtype.UUID{Bytes: u, Valid: true} }
func pgUUIDPtr(u *uuid.UUID) pgtype.UUID {
if u == nil {
return pgtype.UUID{}
}
return pgtype.UUID{Bytes: *u, Valid: true}
}
func uuidPtr(p pgtype.UUID) *uuid.UUID {
if !p.Valid {
return nil
}
id := uuid.UUID(p.Bytes)
return &id
}
func summaryFromRow(r docssqlc.CommitSummary) *Summary {
s := &Summary{
ID: uuid.UUID(r.ID.Bytes),
WorkspaceID: uuid.UUID(r.WorkspaceID.Bytes),
WorktreeID: uuidPtr(r.WorktreeID),
Branch: r.Branch,
CommitSHA: r.CommitSha,
Kind: r.Kind,
Title: r.Title,
BodyMD: r.BodyMd,
Model: r.Model,
Status: r.Status,
Error: r.Error,
}
if r.CreatedAt.Valid {
s.CreatedAt = r.CreatedAt.Time
}
return s
}
func (r *PgRepository) Get(ctx context.Context, wsID uuid.UUID, commitSHA, kind string) (*Summary, error) {
row, err := r.q.GetSummary(ctx, docssqlc.GetSummaryParams{
WorkspaceID: pgUUID(wsID),
CommitSha: commitSHA,
Kind: kind,
})
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
return nil, errs.Wrap(err, errs.CodeInternal, "get commit summary")
}
return summaryFromRow(row), nil
}
func (r *PgRepository) Upsert(ctx context.Context, in UpsertInput) (*Summary, error) {
kind := in.Kind
if kind == "" {
kind = KindCommit
}
status := in.Status
if status == "" {
status = StatusCompleted
}
row, err := r.q.UpsertSummary(ctx, docssqlc.UpsertSummaryParams{
ID: pgUUID(uuid.New()),
WorkspaceID: pgUUID(in.WorkspaceID),
WorktreeID: pgUUIDPtr(in.WorktreeID),
Branch: in.Branch,
CommitSha: in.CommitSHA,
Kind: kind,
Title: in.Title,
BodyMd: in.BodyMD,
Model: in.Model,
Status: status,
Error: in.Error,
})
if err != nil {
return nil, errs.Wrap(err, errs.CodeInternal, "upsert commit summary")
}
return summaryFromRow(row), nil
}