168 lines
5.1 KiB
Go
168 lines
5.1 KiB
Go
package tasks
|
|
|
|
import (
|
|
"context"
|
|
|
|
"inbox/internal/base/timeutil"
|
|
"inbox/internal/domain/task"
|
|
)
|
|
|
|
type Repository interface {
|
|
CreateTask(ctx context.Context, value task.Record, dependencies []task.Dependency) (task.Record, error)
|
|
GetTask(ctx context.Context, taskID string) (task.Record, error)
|
|
ListTasksByTopic(ctx context.Context, topicID string) ([]task.Record, error)
|
|
ListTasksByLane(ctx context.Context, laneID string) ([]task.Record, error)
|
|
UpdateTaskWithDependencies(ctx context.Context, value task.Record, dependencies *[]task.Dependency) (task.Record, error)
|
|
ListTaskDependencies(ctx context.Context, taskID string) ([]task.Dependency, error)
|
|
AppendTaskEvent(ctx context.Context, value task.Event) (task.Event, error)
|
|
ListTaskEvents(ctx context.Context, taskID string) ([]task.Event, error)
|
|
}
|
|
|
|
type Service struct {
|
|
repo Repository
|
|
clock timeutil.Clock
|
|
}
|
|
|
|
type CreateInput struct {
|
|
Task task.Record
|
|
Dependencies []task.Dependency
|
|
}
|
|
|
|
type Patch struct {
|
|
Title *string
|
|
BodyMarkdown *string
|
|
AcceptanceMarkdown *string
|
|
Kind *task.Kind
|
|
Deliverables *[]string
|
|
BatchKey *string
|
|
Status *task.Status
|
|
Priority *int
|
|
TaskOrder *int
|
|
BlockingReasonMarkdown *string
|
|
ResultSummaryMarkdown *string
|
|
AssignedRunID *string
|
|
StartedAt *string
|
|
CompletedAt *string
|
|
Dependencies *[]task.Dependency
|
|
}
|
|
|
|
func NewService(repo Repository, clock timeutil.Clock) *Service {
|
|
if clock == nil {
|
|
clock = timeutil.SystemClock{}
|
|
}
|
|
return &Service{repo: repo, clock: clock}
|
|
}
|
|
|
|
func (s *Service) Create(ctx context.Context, input CreateInput) (task.Record, error) {
|
|
input.Task = task.NormalizeRecord(input.Task)
|
|
if input.Task.Status == "" {
|
|
input.Task.Status = task.StatusDraft
|
|
}
|
|
item, err := s.repo.CreateTask(ctx, input.Task, input.Dependencies)
|
|
if err != nil {
|
|
return task.Record{}, err
|
|
}
|
|
_, _ = s.repo.AppendTaskEvent(ctx, task.Event{
|
|
TaskID: item.ID,
|
|
EventType: "created",
|
|
BodyMarkdown: item.BodyMarkdown,
|
|
CreatedByRoleName: item.CreatedByRoleName,
|
|
CreatedAt: item.CreatedAt,
|
|
})
|
|
return item, nil
|
|
}
|
|
|
|
func (s *Service) Get(ctx context.Context, taskID string) (task.Record, error) {
|
|
return s.repo.GetTask(ctx, taskID)
|
|
}
|
|
|
|
func (s *Service) ListByTopic(ctx context.Context, topicID string) ([]task.Record, error) {
|
|
return s.repo.ListTasksByTopic(ctx, topicID)
|
|
}
|
|
|
|
func (s *Service) ListByLane(ctx context.Context, laneID string) ([]task.Record, error) {
|
|
return s.repo.ListTasksByLane(ctx, laneID)
|
|
}
|
|
|
|
func (s *Service) Dependencies(ctx context.Context, taskID string) ([]task.Dependency, error) {
|
|
return s.repo.ListTaskDependencies(ctx, taskID)
|
|
}
|
|
|
|
func (s *Service) Events(ctx context.Context, taskID string) ([]task.Event, error) {
|
|
return s.repo.ListTaskEvents(ctx, taskID)
|
|
}
|
|
|
|
func (s *Service) Patch(ctx context.Context, taskID string, patch Patch, changedBy string) (task.Record, error) {
|
|
current, err := s.repo.GetTask(ctx, taskID)
|
|
if err != nil {
|
|
return task.Record{}, err
|
|
}
|
|
current = task.NormalizeRecord(current)
|
|
if patch.Title != nil {
|
|
current.Title = *patch.Title
|
|
}
|
|
if patch.BodyMarkdown != nil {
|
|
current.BodyMarkdown = *patch.BodyMarkdown
|
|
}
|
|
if patch.AcceptanceMarkdown != nil {
|
|
current.AcceptanceMarkdown = *patch.AcceptanceMarkdown
|
|
}
|
|
if patch.Kind != nil {
|
|
current.Kind = *patch.Kind
|
|
}
|
|
if patch.Deliverables != nil {
|
|
current.Deliverables = append([]string(nil), (*patch.Deliverables)...)
|
|
}
|
|
if patch.BatchKey != nil {
|
|
current.BatchKey = *patch.BatchKey
|
|
}
|
|
if patch.Status != nil {
|
|
current.Status = *patch.Status
|
|
if current.Status == task.StatusRunning && current.StartedAt == "" {
|
|
current.StartedAt = timeutil.FormatRFC3339(s.clock.Now())
|
|
}
|
|
if (current.Status == task.StatusSucceeded || current.Status == task.StatusFailed || current.Status == task.StatusCancelled) && current.CompletedAt == "" {
|
|
current.CompletedAt = timeutil.FormatRFC3339(s.clock.Now())
|
|
}
|
|
}
|
|
if patch.Priority != nil {
|
|
current.Priority = *patch.Priority
|
|
}
|
|
if patch.TaskOrder != nil {
|
|
current.TaskOrder = *patch.TaskOrder
|
|
}
|
|
if patch.BlockingReasonMarkdown != nil {
|
|
current.BlockingReasonMarkdown = *patch.BlockingReasonMarkdown
|
|
}
|
|
if patch.ResultSummaryMarkdown != nil {
|
|
current.ResultSummaryMarkdown = *patch.ResultSummaryMarkdown
|
|
}
|
|
if patch.AssignedRunID != nil {
|
|
current.AssignedRunID = *patch.AssignedRunID
|
|
}
|
|
if patch.StartedAt != nil {
|
|
current.StartedAt = *patch.StartedAt
|
|
}
|
|
if patch.CompletedAt != nil {
|
|
current.CompletedAt = *patch.CompletedAt
|
|
}
|
|
item, err := s.repo.UpdateTaskWithDependencies(ctx, current, patch.Dependencies)
|
|
if err != nil {
|
|
return task.Record{}, err
|
|
}
|
|
if changedBy != "" {
|
|
_, _ = s.repo.AppendTaskEvent(ctx, task.Event{
|
|
TaskID: item.ID,
|
|
EventType: "updated",
|
|
BodyMarkdown: item.ResultSummaryMarkdown,
|
|
CreatedByRoleName: changedBy,
|
|
CreatedAt: timeutil.FormatRFC3339(s.clock.Now()),
|
|
})
|
|
}
|
|
return item, nil
|
|
}
|
|
|
|
func (s *Service) AppendEvent(ctx context.Context, value task.Event) (task.Event, error) {
|
|
return s.repo.AppendTaskEvent(ctx, value)
|
|
}
|