169 lines
5.2 KiB
Go
169 lines
5.2 KiB
Go
package storage
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"time"
|
|
)
|
|
|
|
// Provider defines the interface for sovereign storage backends.
|
|
// Implementations must ensure data sovereignty compliance for government deployments.
|
|
//
|
|
// Tutus supports multiple storage backends to accommodate national data
|
|
// residency requirements:
|
|
// - NeoFS: Decentralized storage (can be deployed as private network)
|
|
// - Local: Filesystem storage for single-node or NAS deployments
|
|
// - S3-compatible: AWS, Azure, GCP, or sovereign cloud providers
|
|
// - Custom: Nation-specific storage infrastructure
|
|
type Provider interface {
|
|
// Name returns the provider identifier (e.g., "neofs", "local", "s3")
|
|
Name() string
|
|
|
|
// Put stores data and returns a unique identifier for retrieval.
|
|
// The identifier format is provider-specific.
|
|
Put(ctx context.Context, data io.Reader, opts PutOptions) (ObjectID, error)
|
|
|
|
// Get retrieves data by its identifier.
|
|
// Returns ErrNotFound if the object doesn't exist.
|
|
Get(ctx context.Context, id ObjectID) (io.ReadCloser, error)
|
|
|
|
// Delete removes an object from storage.
|
|
// Returns ErrNotFound if the object doesn't exist.
|
|
Delete(ctx context.Context, id ObjectID) error
|
|
|
|
// Exists checks if an object exists in storage.
|
|
Exists(ctx context.Context, id ObjectID) (bool, error)
|
|
|
|
// List returns object IDs matching the given prefix.
|
|
// Use an empty prefix to list all objects in the container.
|
|
List(ctx context.Context, prefix string, opts ListOptions) ([]ObjectInfo, error)
|
|
|
|
// Head retrieves object metadata without downloading content.
|
|
Head(ctx context.Context, id ObjectID) (ObjectInfo, error)
|
|
|
|
// Close releases any resources held by the provider.
|
|
Close() error
|
|
}
|
|
|
|
// BlockStorage extends Provider with blockchain-specific operations.
|
|
type BlockStorage interface {
|
|
Provider
|
|
|
|
// PutBlock stores a block with its index for efficient retrieval.
|
|
PutBlock(ctx context.Context, index uint32, data []byte) (ObjectID, error)
|
|
|
|
// GetBlock retrieves a block by its index.
|
|
GetBlock(ctx context.Context, index uint32) ([]byte, error)
|
|
|
|
// GetBlockRange retrieves multiple blocks efficiently.
|
|
GetBlockRange(ctx context.Context, start, end uint32) ([][]byte, error)
|
|
|
|
// GetLatestBlockIndex returns the highest block index in storage.
|
|
GetLatestBlockIndex(ctx context.Context) (uint32, error)
|
|
}
|
|
|
|
// StateStorage extends Provider with state snapshot operations.
|
|
type StateStorage interface {
|
|
Provider
|
|
|
|
// PutState stores a state snapshot at a specific height.
|
|
PutState(ctx context.Context, height uint32, data io.Reader) (ObjectID, error)
|
|
|
|
// GetState retrieves the state snapshot for a given height.
|
|
GetState(ctx context.Context, height uint32) (io.ReadCloser, error)
|
|
|
|
// GetLatestState returns the most recent state snapshot.
|
|
GetLatestState(ctx context.Context) (height uint32, data io.ReadCloser, err error)
|
|
}
|
|
|
|
// ObjectID uniquely identifies an object within a storage provider.
|
|
type ObjectID struct {
|
|
// Provider is the storage backend identifier
|
|
Provider string
|
|
// Container is the bucket/container/namespace
|
|
Container string
|
|
// ID is the unique object identifier within the container
|
|
ID string
|
|
}
|
|
|
|
// String returns a URI-style representation of the object ID.
|
|
func (o ObjectID) String() string {
|
|
return o.Provider + "://" + o.Container + "/" + o.ID
|
|
}
|
|
|
|
// ObjectInfo contains metadata about a stored object.
|
|
type ObjectInfo struct {
|
|
ID ObjectID
|
|
Size int64
|
|
ContentType string
|
|
Created time.Time
|
|
Modified time.Time
|
|
Checksum string
|
|
Attributes map[string]string
|
|
}
|
|
|
|
// PutOptions configures object storage behavior.
|
|
type PutOptions struct {
|
|
// ContentType specifies the MIME type of the content
|
|
ContentType string
|
|
// Attributes are custom key-value metadata
|
|
Attributes map[string]string
|
|
// Expiration sets automatic deletion time (zero means never)
|
|
Expiration time.Time
|
|
// Replicas specifies the minimum number of copies (provider-dependent)
|
|
Replicas int
|
|
}
|
|
|
|
// ListOptions configures listing behavior.
|
|
type ListOptions struct {
|
|
// MaxResults limits the number of results (0 = no limit)
|
|
MaxResults int
|
|
// Cursor for pagination (provider-specific)
|
|
Cursor string
|
|
// IncludeMetadata fetches full ObjectInfo vs just IDs
|
|
IncludeMetadata bool
|
|
}
|
|
|
|
// Registry manages available storage providers.
|
|
type Registry struct {
|
|
providers map[string]Provider
|
|
}
|
|
|
|
// NewRegistry creates a new provider registry.
|
|
func NewRegistry() *Registry {
|
|
return &Registry{
|
|
providers: make(map[string]Provider),
|
|
}
|
|
}
|
|
|
|
// Register adds a storage provider to the registry.
|
|
func (r *Registry) Register(p Provider) {
|
|
r.providers[p.Name()] = p
|
|
}
|
|
|
|
// Get returns a provider by name.
|
|
func (r *Registry) Get(name string) (Provider, bool) {
|
|
p, ok := r.providers[name]
|
|
return p, ok
|
|
}
|
|
|
|
// List returns all registered provider names.
|
|
func (r *Registry) List() []string {
|
|
names := make([]string, 0, len(r.providers))
|
|
for name := range r.providers {
|
|
names = append(names, name)
|
|
}
|
|
return names
|
|
}
|
|
|
|
// Close closes all registered providers.
|
|
func (r *Registry) Close() error {
|
|
var lastErr error
|
|
for _, p := range r.providers {
|
|
if err := p.Close(); err != nil {
|
|
lastErr = err
|
|
}
|
|
}
|
|
return lastErr
|
|
}
|