feat(coordinator): artifact storage foundation (CTX-05, part 1)
Introduce durable, coordinator-owned artifacts — the model the master plan requires instead of trusting worker-supplied result URIs. - migration 0003: artifacts table + artifact_kind enum, plus nullable input/result_artifact_id columns on jobs and tasks. - domain.Artifact with NewArtifact/SetContent; storage keys derive from a fresh UUID, never from a client filename (no path traversal). - BlobStore and ArtifactRepository ports. - blob.FSStore: filesystem blob storage that streams while hashing (SHA-256), fsyncs, and atomically renames into place — a failed upload leaves neither a committed artifact nor a staging file. Covered by unit tests. - ArtifactRepo (squirrel) and COORDINATOR_STORAGE_DIR config. HTTP upload/download handlers and the switch of result submission to artifact_id come in the next parts.
This commit is contained in:
@@ -9,6 +9,7 @@ package usecase
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@@ -68,6 +69,22 @@ type WorkerRepository interface {
|
||||
Get(ctx context.Context, id uuid.UUID) (*domain.Worker, error)
|
||||
}
|
||||
|
||||
// ArtifactRepository persists artifact metadata. The bytes live in a BlobStore;
|
||||
// this keeps only the record that points at them.
|
||||
type ArtifactRepository interface {
|
||||
Insert(ctx context.Context, a *domain.Artifact) error
|
||||
Get(ctx context.Context, id uuid.UUID) (*domain.Artifact, error)
|
||||
}
|
||||
|
||||
// BlobStore holds artifact bytes, addressed by an opaque storage key. It streams
|
||||
// in both directions so a large shard never has to sit in memory, and reports
|
||||
// the checksum and size it measured while writing — the coordinator's own
|
||||
// numbers, not the client's claim.
|
||||
type BlobStore interface {
|
||||
Put(ctx context.Context, key string, r io.Reader) (sha256 string, size int64, err error)
|
||||
Open(ctx context.Context, key string) (io.ReadCloser, error)
|
||||
}
|
||||
|
||||
// TxManager runs a function inside one database transaction. The transaction
|
||||
// travels in the context, so repositories pick it up without this port ever
|
||||
// mentioning pgx.
|
||||
|
||||
Reference in New Issue
Block a user