All checks were successful
CI/CD / e2e-smoke (push) Has been skipped
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-runners (push) Has been skipped
CI/CD / test-frontend (push) Successful in 6s
CI/CD / test-go-pg (push) Successful in 2m48s
CI/CD / build-and-deploy (push) Successful in 25s
CI/CD / test-sqlite (push) Successful in 2m55s
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.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"`
|
|
}
|