storage

package
v0.0.0-...-54ed9d2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 17, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package storage — Redis-backed store for Helix Cluster OS.

Key schema:

clusteros:cache:{k}             – generic cache entries
clusteros:routing:{sessionID}   – session routing hash (HSET)
clusteros:ratelimit:{subject}   – rate-limit counter (user or "global")
clusteros:events:nodes          – pub/sub channel for NodeEvent messages

Package storage provides a unified storage abstraction for Helix Cluster OS.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrEmptyKey    = errors.New("key cannot be empty")
	ErrKeyNotFound = errors.New("key not found")
	// ErrUnsafeKey is returned by FileStore when a key would resolve to a path
	// outside the store root (e.g. a key containing "../"). Keys are opaque
	// strings in the Store contract, but FileStore maps them onto a filesystem
	// hierarchy; a traversing key must never be allowed to read, write, or
	// delete outside the configured root.
	ErrUnsafeKey = errors.New("key escapes store root")
)

Functions

func CacheKey

func CacheKey(k string) string

CacheKey returns the full Redis key for a generic cache entry.

func NodeEventsChannel

func NodeEventsChannel() string

NodeEventsChannel returns the Redis pub/sub channel for node events.

func RateLimitKey

func RateLimitKey(subject string) string

RateLimitKey returns the full Redis key for a rate-limit counter.

func RoutingKey

func RoutingKey(sessionID string) string

RoutingKey returns the full Redis key for a session routing hash.

Types

type FileStore

type FileStore struct {
	// contains filtered or unexported fields
}

FileStore is a filesystem-backed Store implementation.

func NewFileStore

func NewFileStore(root string) (*FileStore, error)

NewFileStore creates a new FileStore rooted at the given directory.

func (*FileStore) Delete

func (s *FileStore) Delete(key string) error

Delete removes a key file.

func (*FileStore) Get

func (s *FileStore) Get(key string) ([]byte, error)

Get retrieves data by key.

func (*FileStore) List

func (s *FileStore) List(prefix string) ([]string, error)

List returns all keys matching the given prefix, sorted.

func (*FileStore) Put

func (s *FileStore) Put(key string, data []byte) error

Put stores data under key as a file.

type MemoryStore

type MemoryStore struct {
	// contains filtered or unexported fields
}

MemoryStore is an in-memory Store implementation.

func NewMemoryStore

func NewMemoryStore() *MemoryStore

NewMemoryStore creates a new MemoryStore.

func (*MemoryStore) Delete

func (s *MemoryStore) Delete(key string) error

Delete removes a key.

func (*MemoryStore) Get

func (s *MemoryStore) Get(key string) ([]byte, error)

Get retrieves data by key.

func (*MemoryStore) List

func (s *MemoryStore) List(prefix string) ([]string, error)

List returns all keys matching the given prefix, sorted.

func (*MemoryStore) Put

func (s *MemoryStore) Put(key string, data []byte) error

Put stores data under key.

type NodeEvent

type NodeEvent struct {
	// Type is the event kind, e.g. "join", "leave", "update".
	Type string `json:"type"`
	// NodeID identifies the node that changed state.
	NodeID string `json:"node_id"`
	// Payload carries arbitrary per-event metadata.
	Payload map[string]string `json:"payload,omitempty"`
}

NodeEvent represents a cluster-membership change published on the node-events channel. Fields are kept flat (JSON-serialisable) to stay wire-compatible with any subscriber.

type RedisStore

type RedisStore struct {
	// contains filtered or unexported fields
}

RedisStore provides session-routing, pub/sub, and cache helpers backed by Redis. Construct it with NewRedisStore (real go-redis client) or with newRedisStoreFromSeam (tests).

func NewRedisStore

func NewRedisStore(addr string) (*RedisStore, error)

NewRedisStore creates a RedisStore wired to a real go-redis/v9 client. addr is the Redis address, e.g. "127.0.0.1:6379".

func (*RedisStore) GetSessionRouting

func (r *RedisStore) GetSessionRouting(ctx context.Context, sessionID string) (map[string]string, error)

GetSessionRouting returns all fields from the routing hash for sessionID. A missing key returns an empty map and no error.

func (*RedisStore) PublishNodeEvent

func (r *RedisStore) PublishNodeEvent(ctx context.Context, evt NodeEvent) error

PublishNodeEvent serialises evt as JSON and publishes it to clusteros:events:nodes.

func (*RedisStore) SetSessionRouting

func (r *RedisStore) SetSessionRouting(ctx context.Context, sessionID string, fields map[string]string, ttl time.Duration) error

SetSessionRouting stores fields as a Redis hash at clusteros:routing:{sessionID} and sets its TTL. fields must be non-nil; ttl must be > 0.

func (*RedisStore) SubscribeNodeEvents

func (r *RedisStore) SubscribeNodeEvents(ctx context.Context) (<-chan NodeEvent, error)

SubscribeNodeEvents returns a channel that delivers deserialised NodeEvents published on clusteros:events:nodes. The channel is closed when ctx is cancelled or the underlying subscription is torn down.

type S3Config

type S3Config struct {
	// Endpoint is the S3 service base URL (scheme+host[+path]), WITHOUT the
	// bucket. Required.
	Endpoint string
	// Bucket is the target bucket name. Required.
	Bucket string
	// Signer signs each request. Required (use a SigV4Signer for real S3).
	Signer Signer
	// Client is the HTTP client to use. Nil means http.DefaultClient.
	Client *http.Client
}

S3Config configures an S3Store.

type S3Store

type S3Store struct {
	// contains filtered or unexported fields
}

S3Store is an S3-compatible object-storage Store implementation. It speaks the S3 REST API directly over net/http (no aws-sdk) and signs every request with the configured Signer (SigV4 by default). Objects are addressed as {endpoint}/{bucket}/{key}; keys are used verbatim as object paths.

func NewS3Store

func NewS3Store(cfg S3Config) (*S3Store, error)

NewS3Store constructs an S3Store. It validates required fields so a misconfigured store fails loudly at construction rather than on first call.

func (*S3Store) Delete

func (s *S3Store) Delete(key string) error

Delete removes {bucket}/{key}. S3 returns 204 whether or not the object existed, which matches the idempotent-delete contract of the other stores.

func (*S3Store) Exists

func (s *S3Store) Exists(key string) (bool, error)

Exists reports whether {bucket}/{key} exists, via a HEAD request. This is an additive convenience beyond the Store interface.

func (*S3Store) Get

func (s *S3Store) Get(key string) ([]byte, error)

Get downloads {bucket}/{key}. A 404 maps to ErrKeyNotFound.

func (*S3Store) List

func (s *S3Store) List(prefix string) ([]string, error)

List returns all object keys under prefix, sorted, following pagination (continuation tokens) until the listing is exhausted.

func (*S3Store) Put

func (s *S3Store) Put(key string, data []byte) error

Put uploads data to {bucket}/{key}.

type SigV4Signer

type SigV4Signer struct {
	AccessKeyID     string
	SecretAccessKey string
	SessionToken    string // optional; emitted as x-amz-security-token when set
	Region          string
	Service         string // "s3" for object storage
	// contains filtered or unexported fields
}

SigV4Signer implements AWS Signature Version 4 (HMAC-SHA256) over net/http. It is stdlib-only and deterministic given a fixed clock, which is what makes the pinned-vector test possible.

func (*SigV4Signer) Sign

func (s *SigV4Signer) Sign(req *http.Request, payloadHash string) error

Sign computes the SigV4 Authorization header for req and sets it, along with the x-amz-date and x-amz-content-sha256 headers. payloadHash must be the lowercase hex SHA-256 of the exact bytes that will be sent as the body.

type Signer

type Signer interface {
	Sign(req *http.Request, payloadHash string) error
}

Signer signs an outgoing S3 HTTP request in place, adding the Authorization header (and any required x-amz-* headers). It is a pluggable seam so callers can swap in alternative auth (e.g. STS session tokens, anonymous) without touching S3Store. payloadHash is the lowercase hex SHA-256 of the request body, which the signer must fold into the canonical request.

type Store

type Store interface {
	Put(key string, data []byte) error
	Get(key string) ([]byte, error)
	Delete(key string) error
	List(prefix string) ([]string, error)
}

Store is the unified key-value storage interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL