kv

package module
v1.7.1 Latest Latest
Warning

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

Go to latest
Published: Oct 8, 2026 License: MIT Imports: 9 Imported by: 7

Documentation

Overview

Package kv provides a command-oriented data access layer for key-value, cache, and document stores. It is part of the Grove ecosystem and shares Grove's hook, plugin, CRDT, and internal infrastructure.

Grove KV is not a fake SQL abstraction over SET/GET — it exposes native idioms per store (Redis pipelines, DynamoDB expressions, Memcached CAS) while providing a unified Store interface for common operations.

Quick Start

rdb := redisdriver.New()  // import "github.com/xraph/grove/kv/drivers/redisdriver"
rdb.Open(ctx, "redis://localhost:6379/0")

store, _ := kv.Open(rdb,
    kv.WithCodec(codec.JSON()),
)
defer store.Close()

// Basic Get/Set
store.Set(ctx, "user:1", user, kv.WithTTL(time.Hour))
store.Get(ctx, "user:1", &user)

Design Principles

  • Command-oriented, not query-oriented
  • Native idioms per store via Unwrap()
  • Shared DNA with Grove (hooks, plugins, CRDT, observability)
  • CRDT-native distributed state
  • Struct-aware serialization via codecs
  • First-class TTL and eviction

Index

Constants

View Source
const (
	OpGet    hook.Operation = 100 + iota // GET key
	OpSet                                // SET key value
	OpDelete                             // DEL key [key ...]
	OpExists                             // EXISTS key [key ...]
	OpMGet                               // MGET key [key ...]
	OpMSet                               // MSET key value [key value ...]
	OpTTL                                // TTL key
	OpExpire                             // EXPIRE key seconds
	OpScan                               // SCAN cursor MATCH pattern

	// Collection operations. A hook sees these the same way it sees the
	// scalar commands above, which is what lets metrics, tracing, and
	// tests observe the work a queue or an index actually does rather
	// than only the plain key reads around it.
	OpZAdd    // ZADD key score member [score member ...]
	OpZRange  // ZRANGEBYSCORE key min max
	OpZRem    // ZREM key member [member ...]
	OpZCard   // ZCARD key
	OpZScore  // ZSCORE key member
	OpSAdd    // SADD key member [member ...]
	OpSRem    // SREM key member [member ...]
	OpSMbrs   // SMEMBERS key
	OpSCard   // SCARD key
	OpSIsMbr  // SISMEMBER key member
	OpHSet    // HSET key field value [field value ...]
	OpHGet    // HGET key field
	OpHGetAll // HGETALL key
	OpHDel    // HDEL key field [field ...]
	OpHLen    // HLEN key
	OpPublish // PUBLISH channel message
	OpSubscr  // SUBSCRIBE channel
	OpEval    // EVAL script numkeys key [key ...] arg [arg ...]
	OpXAdd    // XADD stream field value [field value ...]
	OpXRange  // XRANGE stream start end
	OpXDel    // XDEL stream id [id ...]
	OpXLen    // XLEN stream
)

KV-specific operations. These extend hook.Operation at an offset to avoid collision with ORM operations (OpSelect, OpInsert, etc.).

Variables

View Source
var (
	// ErrNotFound is returned when a key does not exist.
	ErrNotFound = errors.New("kv: key not found")

	// ErrConflict is returned when a CAS operation detects a version conflict.
	ErrConflict = errors.New("kv: version conflict (CAS mismatch)")

	// ErrStoreClosed is returned when an operation is attempted on a closed store.
	ErrStoreClosed = errors.New("kv: store has been closed")

	// ErrScriptNotLoaded is returned when EvalSHA names a digest the
	// server no longer has cached. Callers recover by loading the script
	// again and retrying; a script cache is not durable across restarts.
	ErrScriptNotLoaded = errors.New("kv: script not loaded")

	// ErrNotSupported is returned when a driver does not support the requested operation.
	ErrNotSupported = errors.New("kv: operation not supported by driver")

	// ErrHookDenied is returned when a hook denies the operation.
	ErrHookDenied = errors.New("kv: hook denied the operation")

	// ErrHookKeyCount is returned when a pre-query hook changes how many
	// keys a command touches. Hooks may rewrite keys, as a namespace does,
	// but results are matched to the caller's keys by position.
	ErrHookKeyCount = errors.New("kv: hook changed the number of keys")

	// ErrCodecEncode is returned when value encoding fails.
	ErrCodecEncode = errors.New("kv: codec encode failed")

	// ErrCodecDecode is returned when value decoding fails.
	ErrCodecDecode = errors.New("kv: codec decode failed")

	// ErrKeyEmpty is returned when an empty key is provided.
	ErrKeyEmpty = errors.New("kv: key must not be empty")

	// ErrNilValue is returned when a nil value is provided to Set.
	ErrNilValue = errors.New("kv: value must not be nil")
)

Sentinel errors returned by KV operations.

Functions

func CommandName

func CommandName(op hook.Operation) string

CommandName returns a human-readable name for a KV operation.

func Drivers

func Drivers() []string

Drivers returns the names of all registered KV drivers.

func OpenDriver

func OpenDriver(ctx context.Context, name, dsn string) (driver.Driver, error)

OpenDriver creates a new driver instance by its registered name and opens it with the given DSN. Returns an error if no factory is registered for the given name.

func RegisterDriver

func RegisterDriver(name string, factory DriverFactory)

RegisterDriver registers a named KV driver factory. It is typically called from a driver package's init() function. Subsequent calls with the same name overwrite the previous registration.

Example (in redisdriver package):

func init() {
    kv.RegisterDriver("redis", func() driver.Driver { return New() })
}

Types

type Batch

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

Batch provides a fluent builder for multi-key operations.

func NewBatch

func NewBatch(store *Store) *Batch

NewBatch creates a new batch operation builder.

func (*Batch) Delete

func (b *Batch) Delete(keys ...string) *Batch

Delete adds keys to be deleted in the batch.

func (*Batch) Exec

func (b *Batch) Exec(ctx context.Context) (*BatchResult, error)

Exec executes all queued batch operations.

func (*Batch) Get

func (b *Batch) Get(keys ...string) *Batch

Get adds a key to be retrieved in the batch.

func (*Batch) Set

func (b *Batch) Set(key string, value any) *Batch

Set adds a key-value pair to the batch.

func (*Batch) WithOptions

func (b *Batch) WithOptions(opts ...SetOption) *Batch

WithOptions sets options for the batch Set operations.

type BatchResult

type BatchResult struct {
	// Values holds the raw bytes retrieved by Get operations, keyed by key.
	Values map[string][]byte

	// Written is the number of keys written.
	Written int64

	// Deleted is the number of keys deleted.
	Deleted int64
}

BatchResult holds the results of a batch operation.

func (*BatchResult) Decode

func (r *BatchResult) Decode(key string, dest any, c codec.Codec) error

Decode decodes a value from the batch result into dest.

type DriverFactory

type DriverFactory func() driver.Driver

DriverFactory is a function that creates a new, unconnected KV driver instance. Drivers register factories via RegisterDriver so that callers can create drivers by name (e.g., from YAML configuration) without importing driver packages directly.

Each driver module should register its factory in an init() function.

type Entry

type Entry[T any] struct {
	// Key is the full key string.
	Key string

	// Value is the decoded value.
	Value T

	// TTL is the remaining time-to-live. Zero means no expiry.
	TTL time.Duration

	// Version is the CAS version (if supported by the driver).
	Version uint64

	// Metadata carries arbitrary key-value metadata.
	Metadata map[string]string
}

Entry is a typed wrapper around a KV value that carries metadata.

func (Entry[T]) HasTTL

func (e Entry[T]) HasTTL() bool

HasTTL returns true if the entry has a TTL set.

type Option

type Option func(*options)

Option configures a Store during Open.

func WithCodec

func WithCodec(c codec.Codec) Option

WithCodec sets the default codec for the store.

func WithHook

func WithHook(h any, scope ...hook.Scope) Option

WithHook registers a middleware hook with the store. The hook must implement hook.PreQueryHook and/or hook.PostQueryHook.

type SetOption

type SetOption func(*setOptions)

SetOption configures a single Set operation.

func WithCAS

func WithCAS(version uint64) SetOption

WithCAS sets the expected version for a Compare-And-Swap operation.

func WithNX

func WithNX() SetOption

WithNX sets the key only if it does not already exist.

func WithTTL

func WithTTL(d time.Duration) SetOption

WithTTL sets the TTL for the Set operation.

func WithXX

func WithXX() SetOption

WithXX sets the key only if it already exists.

type Store

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

Store is the top-level KV handle. It manages the driver connection, hook engine, default codec, and provides entry points for all KV operations.

func Open

func Open(drv driver.Driver, opts ...Option) (*Store, error)

Open creates a new Store with the given driver and options. The driver must already be connected (call driver.Open before kv.Open).

func (*Store) Close

func (s *Store) Close() error

Close closes the store and releases all resources.

func (*Store) Codec

func (s *Store) Codec() codec.Codec

Codec returns the default codec.

func (*Store) Delete

func (s *Store) Delete(ctx context.Context, keys ...string) error

Delete removes one or more keys.

func (*Store) Driver

func (s *Store) Driver() driver.Driver

Driver returns the underlying KV driver.

func (*Store) Eval added in v1.6.1

func (s *Store) Eval(ctx context.Context, script string, keys []string, args ...any) (any, error)

Eval runs a script against the given keys and arguments.

func (*Store) EvalSHA added in v1.6.1

func (s *Store) EvalSHA(ctx context.Context, sha string, keys []string, args ...any) (any, error)

EvalSHA runs a loaded script by digest.

It returns ErrScriptNotLoaded when the server has dropped the script, which happens across restarts: callers reload and retry rather than treating it as a failure.

func (*Store) Exists

func (s *Store) Exists(ctx context.Context, keys ...string) (int64, error)

Exists returns the count of keys that exist.

func (*Store) Expire

func (s *Store) Expire(ctx context.Context, key string, ttl time.Duration) error

Expire sets the TTL on an existing key.

func (*Store) Get

func (s *Store) Get(ctx context.Context, key string, dest any) error

Get retrieves the value for key and decodes it into dest.

func (*Store) GetRaw

func (s *Store) GetRaw(ctx context.Context, key string) ([]byte, error)

GetRaw retrieves the raw bytes for key without codec decoding. Used by Keyspace[T] to apply its own codec.

func (*Store) HDel added in v1.6.1

func (s *Store) HDel(ctx context.Context, key string, fields ...string) (int64, error)

HDel removes fields from a hash.

func (*Store) HGet added in v1.6.1

func (s *Store) HGet(ctx context.Context, key, field string) ([]byte, error)

HGet returns one field's value, or ErrNotFound when it is absent.

func (*Store) HGetAll added in v1.6.1

func (s *Store) HGetAll(ctx context.Context, key string) (map[string][]byte, error)

HGetAll returns every field of a hash.

func (*Store) HLen added in v1.6.1

func (s *Store) HLen(ctx context.Context, key string) (int64, error)

HLen returns the number of fields in a hash.

func (*Store) HSet added in v1.6.1

func (s *Store) HSet(ctx context.Context, key string, fields map[string][]byte) (int64, error)

HSet sets fields on a hash.

func (*Store) Hooks

func (s *Store) Hooks() *hook.Engine

Hooks returns the hook engine for registering additional hooks.

func (*Store) MGet

func (s *Store) MGet(ctx context.Context, keys []string, dest map[string]any) error

MGet retrieves multiple keys. dest must be a pointer to a map[string]any or similar.

func (*Store) MGetRaw added in v1.6.1

func (s *Store) MGetRaw(ctx context.Context, keys []string) ([][]byte, error)

MGetRaw reads many keys, returning a slice positionally aligned with keys and holding nil where a key was absent.

It is the raw counterpart to MGet, which decodes into a map and so cannot say which key produced which value when some are missing. Positional results are what a caller filtering a batch needs.

func (*Store) MSet

func (s *Store) MSet(ctx context.Context, pairs map[string]any, opts ...SetOption) error

MSet sets multiple key-value pairs.

func (*Store) Ping

func (s *Store) Ping(ctx context.Context) error

Ping verifies the store is reachable.

func (*Store) Publish added in v1.6.1

func (s *Store) Publish(ctx context.Context, channel string, message []byte) error

Publish sends a message to a channel.

Delivery is at-most-once and only to subscribers connected at the moment of publication: this is a notification primitive, not a queue. Callers that must not miss a message need a durable structure behind it, with the message serving only to shorten the latency.

func (*Store) SAdd added in v1.6.1

func (s *Store) SAdd(ctx context.Context, key string, members ...string) (int64, error)

SAdd adds members to a set.

func (*Store) SCard added in v1.6.1

func (s *Store) SCard(ctx context.Context, key string) (int64, error)

SCard returns the number of members in a set.

func (*Store) SIsMember added in v1.6.1

func (s *Store) SIsMember(ctx context.Context, key, member string) (bool, error)

SIsMember reports whether a member is present in a set.

func (*Store) SMembers added in v1.6.1

func (s *Store) SMembers(ctx context.Context, key string) ([]string, error)

SMembers returns every member of a set.

func (*Store) SRem added in v1.6.1

func (s *Store) SRem(ctx context.Context, key string, members ...string) (int64, error)

SRem removes members from a set.

func (*Store) Scan

func (s *Store) Scan(ctx context.Context, pattern string, fn func(key string) error) error

Scan iterates over keys matching pattern, calling fn for each.

func (*Store) ScriptLoad added in v1.6.1

func (s *Store) ScriptLoad(ctx context.Context, script string) (string, error)

ScriptLoad caches a script and returns its digest.

func (*Store) Set

func (s *Store) Set(ctx context.Context, key string, value any, opts ...SetOption) error

Set encodes value and stores it under key.

func (*Store) SetRaw

func (s *Store) SetRaw(ctx context.Context, key string, value []byte, opts ...SetOption) error

SetRaw stores raw bytes under key without codec encoding. Used by Keyspace[T] to apply its own codec.

func (*Store) Subscribe added in v1.6.1

func (s *Store) Subscribe(ctx context.Context, channel string, handler func(msg []byte)) error

Subscribe registers a handler for a channel, called for every message until the context ends.

func (*Store) SupportsHashes added in v1.6.1

func (s *Store) SupportsHashes() bool

SupportsHashes reports whether the driver has hash maps.

func (*Store) SupportsPubSub added in v1.6.1

func (s *Store) SupportsPubSub() bool

SupportsPubSub reports whether the driver has publish/subscribe.

func (*Store) SupportsScripts added in v1.6.1

func (s *Store) SupportsScripts() bool

SupportsScripts reports whether the driver runs server-side scripts.

func (*Store) SupportsSets added in v1.6.1

func (s *Store) SupportsSets() bool

SupportsSets reports whether the driver has unordered sets.

func (*Store) SupportsSortedSets added in v1.6.1

func (s *Store) SupportsSortedSets() bool

SupportsSortedSets reports whether the driver has sorted sets.

func (*Store) SupportsStreams added in v1.6.1

func (s *Store) SupportsStreams() bool

SupportsStreams reports whether the driver has append-only streams.

func (*Store) TTL

func (s *Store) TTL(ctx context.Context, key string) (time.Duration, error)

TTL returns the remaining TTL for key.

func (*Store) XAdd added in v1.6.1

func (s *Store) XAdd(ctx context.Context, stream string, values map[string][]byte) (string, error)

XAdd appends an entry to a stream and returns its assigned ID.

func (*Store) XDel added in v1.6.1

func (s *Store) XDel(ctx context.Context, stream string, ids ...string) (int64, error)

XDel removes entries from a stream by ID.

func (*Store) XLen added in v1.6.1

func (s *Store) XLen(ctx context.Context, stream string) (int64, error)

XLen returns the number of entries in a stream.

func (*Store) XRange added in v1.6.1

func (s *Store) XRange(
	ctx context.Context, stream, start, stop string, count int64,
) ([]driver.StreamMessage, error)

XRange returns entries between start and stop inclusive, oldest first.

func (*Store) ZAdd added in v1.6.1

func (s *Store) ZAdd(ctx context.Context, key string, members ...driver.ScoredMember) (int64, error)

ZAdd inserts or updates members of a sorted set.

func (*Store) ZCard added in v1.6.1

func (s *Store) ZCard(ctx context.Context, key string) (int64, error)

ZCard returns the number of members in a sorted set.

func (*Store) ZRange added in v1.6.1

func (s *Store) ZRange(ctx context.Context, key string, spec driver.RangeSpec) ([]string, error)

ZRange returns members within the spec, ordered by score.

func (*Store) ZRangeWithScores added in v1.6.1

func (s *Store) ZRangeWithScores(
	ctx context.Context, key string, spec driver.RangeSpec,
) ([]driver.ScoredMember, error)

ZRangeWithScores is ZRange carrying each member's score.

func (*Store) ZRem added in v1.6.1

func (s *Store) ZRem(ctx context.Context, key string, members ...string) (int64, error)

ZRem removes members from a sorted set.

func (*Store) ZScore added in v1.6.1

func (s *Store) ZScore(ctx context.Context, key, member string) (float64, bool, error)

ZScore returns a member's score, and false when it is absent.

Directories

Path Synopsis
Package codec provides serialization codecs for KV values.
Package codec provides serialization codecs for KV values.
Package kvcrdt bridges grove/crdt types into KV storage, enabling distributed, eventually-consistent state without a relational database.
Package kvcrdt bridges grove/crdt types into KV storage, enabling distributed, eventually-consistent state without a relational database.
Package driver defines the interface contract that every KV backend must implement.
Package driver defines the interface contract that every KV backend must implement.
drivers
redisdriver module
extension module
Package keyspace provides typed, namespaced key partitions for Grove KV.
Package keyspace provides typed, namespaced key partitions for Grove KV.
Package kvtest provides a mock KV driver and conformance test suite.
Package kvtest provides a mock KV driver and conformance test suite.
Package middleware provides composable middleware for Grove KV operations.
Package middleware provides composable middleware for Grove KV operations.
Package extension provides application-level patterns built on Grove KV.
Package extension provides application-level patterns built on Grove KV.

Jump to

Keyboard shortcuts

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