feat(coordinator): artifact upload/download endpoints (CTX-05, part 2)
Wire the artifact storage foundation to HTTP.
- PUT /tasks/{id}/artifacts/{filename}: a worker streams a partial result;
the coordinator verifies lease ownership (foreign worker → 409), streams
the bytes to blob storage while hashing, and records the metadata. An
orphaned blob from a failed metadata insert is cleaned up.
- GET /artifacts/{id}/download: streams an artifact back with its content
type, length, and checksum.
- Ownership is read with a new non-locking TaskRepository.Get, so no row lock
is held across a long upload. Identity travels in X-Worker-ID / X-Task-Attempt
headers per the contract; upload/download bypass the short request timeout.
- docker-compose mounts ./data for durable artifact storage; smoke and
requests.http exercise an upload → foreign-409 → download round-trip.
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
package usecase
|
||||
|
||||
import "github.com/google/uuid"
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Use-case boundary types. Adapters map their wire formats onto these, so the
|
||||
// HTTP shape can change without touching business code.
|
||||
@@ -46,6 +50,15 @@ type CompleteTaskInput struct {
|
||||
Metrics map[string]any
|
||||
}
|
||||
|
||||
type UploadArtifactInput struct {
|
||||
TaskID uuid.UUID
|
||||
WorkerID string
|
||||
Attempt int
|
||||
Filename string
|
||||
ContentType string
|
||||
Body io.Reader
|
||||
}
|
||||
|
||||
type FailTaskInput struct {
|
||||
TaskID uuid.UUID
|
||||
WorkerID string
|
||||
|
||||
Reference in New Issue
Block a user