// Package port defines interfaces (ports) for external dependencies. package port import ( "context" "time" ) // WorkQueue defines operations for the worker pool task queue. // Unlike CommandQueue (project-specific claudebox commands), WorkQueue // supports generic tasks that any worker in the pool can claim and execute. type WorkQueue interface { // Enqueue adds a task to the queue. // Returns the task ID. Enqueue(ctx context.Context, task *WorkTask) (string, error) // Dequeue atomically claims the next available task for a worker. // Uses FOR UPDATE SKIP LOCKED for concurrent worker safety. // Returns nil if no tasks are available. Dequeue(ctx context.Context, workerID string) (*WorkTask, error) // Complete marks a task as successfully completed with results. Complete(ctx context.Context, taskID string, result *WorkResult) error // Fail marks a task as failed with an error message. // If retry_count < max_retries, the task will be re-queued as pending. Fail(ctx context.Context, taskID string, errMsg string) error // Cancel marks a pending task as cancelled. // Returns an error if the task is not in pending status. Cancel(ctx context.Context, taskID string) error // GetTask retrieves a task by ID. GetTask(ctx context.Context, taskID string) (*WorkTask, error) // ListByProject returns tasks for a project with optional status filter and pagination. ListByProject(ctx context.Context, projectID string, status *WorkTaskStatus, opts WorkListOptions) (*WorkListResult, error) // GetStats returns queue statistics. GetStats(ctx context.Context) (*WorkQueueStats, error) // CleanupOld removes completed/failed/cancelled tasks older than the specified duration. CleanupOld(ctx context.Context, olderThan time.Duration) (int64, error) // RequeueStale re-queues tasks that have been running longer than the timeout. // This handles workers that crashed without reporting completion. RequeueStale(ctx context.Context, timeout time.Duration) (int64, error) } // WorkTaskStatus represents the status of a work task. type WorkTaskStatus string const ( WorkTaskStatusPending WorkTaskStatus = "pending" WorkTaskStatusRunning WorkTaskStatus = "running" WorkTaskStatusCompleted WorkTaskStatus = "completed" WorkTaskStatusFailed WorkTaskStatus = "failed" WorkTaskStatusCancelled WorkTaskStatus = "cancelled" ) // IsValid returns true if the status is a known valid status. func (s WorkTaskStatus) IsValid() bool { switch s { case WorkTaskStatusPending, WorkTaskStatusRunning, WorkTaskStatusCompleted, WorkTaskStatusFailed, WorkTaskStatusCancelled: return true } return false } // WorkTaskType represents the type of work task. type WorkTaskType string const ( WorkTaskTypeBuild WorkTaskType = "build" WorkTaskTypeTest WorkTaskType = "test" WorkTaskTypeDeploy WorkTaskType = "deploy" WorkTaskTypeCustom WorkTaskType = "custom" ) // IsValid returns true if the task type is a known valid type. func (t WorkTaskType) IsValid() bool { switch t { case WorkTaskTypeBuild, WorkTaskTypeTest, WorkTaskTypeDeploy, WorkTaskTypeCustom: return true } return false } // WorkTask represents a task in the work queue. type WorkTask struct { // ID is the unique task identifier. ID string // ProjectID is the project this task belongs to. ProjectID string // Type is the task type (build, test, deploy, custom). Type WorkTaskType // Spec contains task-specific parameters. // For build tasks: template, prompt, variables, auto_deploy, git_url // For test tasks: test_command, git_url // For deploy tasks: image, replicas, env Spec map[string]any // Status is the current task status. Status WorkTaskStatus // Priority determines execution order (higher = more urgent). Priority int // WorkerID is the ID of the worker that claimed this task. WorkerID string // CallbackURL is the webhook URL for completion notification. CallbackURL string // CreatedAt is when the task was created. CreatedAt time.Time // StartedAt is when a worker started executing the task. StartedAt *time.Time // CompletedAt is when the task finished (success or failure). CompletedAt *time.Time // Result contains the task output (if completed). Result *WorkResult // Error contains the error message (if failed). Error string // RetryCount is the number of retry attempts. RetryCount int // MaxRetries is the maximum allowed retry attempts. MaxRetries int } // WorkResult contains the result of a completed task. type WorkResult struct { // Output is the main output from task execution. Output string `json:"output,omitempty"` // Artifacts contains named artifacts from the task. // For build tasks: commit_sha, deploy_url, etc. Artifacts map[string]string `json:"artifacts,omitempty"` } // WorkQueueStats contains queue statistics. type WorkQueueStats struct { // Pending is the count of pending tasks. Pending int64 `json:"pending"` // Running is the count of running tasks. Running int64 `json:"running"` // Completed is the count of completed tasks (last 24h). Completed int64 `json:"completed"` // Failed is the count of failed tasks (last 24h). Failed int64 `json:"failed"` // Cancelled is the count of cancelled tasks (last 24h). Cancelled int64 `json:"cancelled"` // OldestPending is the age of the oldest pending task. OldestPending *time.Duration `json:"oldest_pending,omitempty"` } // WorkListOptions contains pagination options for listing tasks. type WorkListOptions struct { // Limit is the maximum number of tasks to return (default: 50, max: 100). Limit int // Offset is the number of tasks to skip (for pagination). Offset int } // DefaultWorkListOptions returns options with default values. func DefaultWorkListOptions() WorkListOptions { return WorkListOptions{ Limit: 50, Offset: 0, } } // Normalize applies defaults and limits to the options. func (o *WorkListOptions) Normalize() { if o.Limit <= 0 { o.Limit = 50 } if o.Limit > 100 { o.Limit = 100 } if o.Offset < 0 { o.Offset = 0 } } // WorkListResult contains paginated task results. type WorkListResult struct { // Tasks is the list of tasks. Tasks []*WorkTask // Total is the total count of matching tasks (for pagination metadata). Total int64 // Limit is the limit that was applied. Limit int // Offset is the offset that was applied. Offset int }