Files
ai-workflow/inbox/internal/store/sqlite/task_graph_versions.go
T

156 lines
4.4 KiB
Go

package sqlite
import (
"context"
"database/sql"
"fmt"
"inbox/internal/domain/taskgraph"
)
func (s *Store) CreateTaskGraphVersion(ctx context.Context, value taskgraph.Record) (taskgraph.Record, error) {
if err := value.Validate(); err != nil {
return taskgraph.Record{}, err
}
if value.ID == "" {
id, err := s.newID("task-graph-version")
if err != nil {
return taskgraph.Record{}, err
}
value.ID = id
}
value.CreatedAt = coalesceString(value.CreatedAt, s.now())
if _, err := s.db.ExecContext(ctx, `
INSERT INTO task_graph_versions(
id, topic_id, version, status, plan_json, plan_summary_markdown,
created_by_role_name, created_at, confirmed_at, supersedes_graph_version_id
)
VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`,
value.ID,
value.TopicID,
value.Version,
string(value.Status),
value.PlanJSON,
value.PlanSummaryMarkdown,
value.CreatedByRoleName,
value.CreatedAt,
nullableString(value.ConfirmedAt),
nullableString(value.SupersedesGraphVersionID),
); err != nil {
return taskgraph.Record{}, fmt.Errorf("create task graph version: %w", err)
}
return value, nil
}
func (s *Store) GetTaskGraphVersion(ctx context.Context, graphVersionID string) (taskgraph.Record, error) {
row := s.db.QueryRowContext(ctx, `
SELECT id, topic_id, version, status, plan_json, plan_summary_markdown,
created_by_role_name, created_at, confirmed_at, supersedes_graph_version_id
FROM task_graph_versions
WHERE id = ?
`, graphVersionID)
return scanTaskGraphVersion(row)
}
func (s *Store) ListTaskGraphVersionsByTopic(ctx context.Context, topicID string) ([]taskgraph.Record, error) {
rows, err := s.db.QueryContext(ctx, `
SELECT id, topic_id, version, status, plan_json, plan_summary_markdown,
created_by_role_name, created_at, confirmed_at, supersedes_graph_version_id
FROM task_graph_versions
WHERE topic_id = ?
ORDER BY version DESC, created_at DESC
`, topicID)
if err != nil {
return nil, fmt.Errorf("list task graph versions by topic: %w", err)
}
defer rows.Close()
var out []taskgraph.Record
for rows.Next() {
item, err := scanTaskGraphVersion(rows)
if err != nil {
return nil, err
}
out = append(out, item)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate task graph versions: %w", err)
}
return out, nil
}
func (s *Store) GetLatestTaskGraphVersionByTopic(ctx context.Context, topicID string) (taskgraph.Record, error) {
row := s.db.QueryRowContext(ctx, `
SELECT id, topic_id, version, status, plan_json, plan_summary_markdown,
created_by_role_name, created_at, confirmed_at, supersedes_graph_version_id
FROM task_graph_versions
WHERE topic_id = ?
ORDER BY version DESC, created_at DESC
LIMIT 1
`, topicID)
return scanTaskGraphVersion(row)
}
func (s *Store) UpdateTaskGraphVersion(ctx context.Context, value taskgraph.Record) (taskgraph.Record, error) {
if value.ID == "" {
return taskgraph.Record{}, fmt.Errorf("task graph version id is required")
}
before, err := s.GetTaskGraphVersion(ctx, value.ID)
if err != nil {
return taskgraph.Record{}, err
}
value.TopicID = before.TopicID
value.Version = before.Version
value.CreatedAt = before.CreatedAt
if err := value.Validate(); err != nil {
return taskgraph.Record{}, err
}
if _, err := s.db.ExecContext(ctx, `
UPDATE task_graph_versions
SET status = ?, plan_json = ?, plan_summary_markdown = ?, created_by_role_name = ?,
confirmed_at = ?, supersedes_graph_version_id = ?
WHERE id = ?
`,
string(value.Status),
value.PlanJSON,
value.PlanSummaryMarkdown,
value.CreatedByRoleName,
nullableString(value.ConfirmedAt),
nullableString(value.SupersedesGraphVersionID),
value.ID,
); err != nil {
return taskgraph.Record{}, fmt.Errorf("update task graph version: %w", err)
}
return s.GetTaskGraphVersion(ctx, value.ID)
}
func scanTaskGraphVersion(s scanner) (taskgraph.Record, error) {
var item taskgraph.Record
var status string
var confirmedAt sql.NullString
var supersedesID sql.NullString
if err := s.Scan(
&item.ID,
&item.TopicID,
&item.Version,
&status,
&item.PlanJSON,
&item.PlanSummaryMarkdown,
&item.CreatedByRoleName,
&item.CreatedAt,
&confirmedAt,
&supersedesID,
); err != nil {
return taskgraph.Record{}, err
}
item.Status = taskgraph.Status(status)
if confirmedAt.Valid {
item.ConfirmedAt = confirmedAt.String
}
if supersedesID.Valid {
item.SupersedesGraphVersionID = supersedesID.String
}
return item, nil
}