All checks were successful
CI/CD / detect-changes (pull_request) Successful in 4s
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-frontend (pull_request) Successful in 5s
CI/CD / test-sqlite (pull_request) Successful in 2m54s
CI/CD / test-go-pg (pull_request) Successful in 2m56s
CI/CD / build-and-deploy (pull_request) Successful in 1m1s
Clean up channels-era dead code, align migrations, add 92 tests, and fix backup download + admin storage tab bugs before v0.8.x kernel expansion. Critical fixes: - Remove `channels` from allowedViews in db_module.go - Fix 5 dead API routes in workflow.html → public workflow API - Fix RenderWorkflow handler to use route param as entry token Dead code removal: - Delete SeedTestChannel(), RunContext.ChannelID, webhook.ChannelID - Fix stale comments in storage.go, prometheus.go, workflow_module.go Migration hygiene: - Add SQLite placeholder 013_cluster_registry.sql, renumber to 014 - Compat rename in migrate.go for existing SQLite databases - Document missing migration 008 in both 009 files Test coverage: - 82 workflow routing tests (all operators, branch rules, stage resolution) - 10 middleware tests (permissions, admin, rate limiter) Bug fixes: - Remove dead Admin Storage tab from System category - Fix backup download: sw.auth.token() → sw.auth._getToken() Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
74 lines
2.5 KiB
Go
74 lines
2.5 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
)
|
|
|
|
// ── Errors ─────────────────────────────────
|
|
|
|
var (
|
|
// ErrNotFound is returned when a requested object does not exist.
|
|
ErrNotFound = errors.New("storage: object not found")
|
|
|
|
// ErrNotConfigured is returned when storage operations are attempted
|
|
// but no backend has been configured or the backend is unhealthy.
|
|
ErrNotConfigured = errors.New("storage: backend not configured")
|
|
)
|
|
|
|
// ── ObjectStore Interface ──────────────────
|
|
|
|
// ObjectStore is the abstraction for blob storage.
|
|
// Implementations: PVC (filesystem), S3 (minio-go v7).
|
|
//
|
|
// Keys are slash-delimited paths relative to the storage root:
|
|
//
|
|
// ext/{package_id}/{file_id}_{filename}
|
|
//
|
|
// Implementations must create intermediate directories as needed.
|
|
type ObjectStore interface {
|
|
// Put writes data to the given key.
|
|
// Creates parent directories as needed. Overwrites if exists.
|
|
Put(ctx context.Context, key string, r io.Reader, size int64, contentType string) error
|
|
|
|
// Get returns a reader for the given key.
|
|
// Returns the reader, size in bytes, content type, and error.
|
|
// Caller must close the returned reader.
|
|
// Returns ErrNotFound if key does not exist.
|
|
Get(ctx context.Context, key string) (io.ReadCloser, int64, string, error)
|
|
|
|
// Delete removes the object at key.
|
|
// No error if the key does not exist (idempotent).
|
|
Delete(ctx context.Context, key string) error
|
|
|
|
// DeletePrefix removes all objects under the given prefix.
|
|
// Used for bulk cleanup (e.g. extension uninstall).
|
|
// Example: DeletePrefix(ctx, "ext/{package_id}/")
|
|
DeletePrefix(ctx context.Context, prefix string) error
|
|
|
|
// Exists checks if an object exists at key without reading it.
|
|
Exists(ctx context.Context, key string) (bool, error)
|
|
|
|
// Healthy returns nil if the backend is operational (writable).
|
|
Healthy(ctx context.Context) error
|
|
|
|
// Stats returns aggregate storage statistics.
|
|
Stats(ctx context.Context) (*StorageStats, error)
|
|
|
|
// Backend returns the backend type identifier ("pvc", "s3").
|
|
Backend() string
|
|
}
|
|
|
|
// StorageStats holds aggregate storage metrics.
|
|
type StorageStats struct {
|
|
Backend string `json:"backend"`
|
|
Path string `json:"path,omitempty"` // PVC only
|
|
Endpoint string `json:"endpoint,omitempty"` // S3 only
|
|
Bucket string `json:"bucket,omitempty"` // S3 only
|
|
Healthy bool `json:"healthy"`
|
|
Configured bool `json:"configured"`
|
|
TotalFiles int64 `json:"total_files"`
|
|
TotalBytes int64 `json:"total_bytes"`
|
|
}
|