hermes

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2025 License: MIT Imports: 15 Imported by: 0

README

In-Memory Data Store with Transactions and Pub/Sub

A high-performance thread-safe in-memory data store with advanced features for Go applications.

Features

  • 🧩 ACID Transactions with rollback support
  • 📡 Publish-Subscribe messaging pattern
  • ⏲ Automatic Expiration (TTL) for keys
  • ⚡ Atomic Operations (CAS, INCR/DECR, LPUSH/RPUSH)
  • 🔍 Type-Safe Operations for lists and counters
  • 📊 Built-in Logging with configurable output

Installation

go get github.com/themedef/go-hermes

Basic Usage

import (
    "context"
    "time"
    "github.com/themedef/go-hermes"
)

func main() {
    // Initialize store
    cfg := hermes.Config{
        EnableLogging:   true,
        LogFile:         "data.log",
    }
    db := hermes.NewStore(cfg)

    // Basic operations
    ctx := context.Background()
    
    // Set key with TTL
    err := db.Set(ctx, "session:123", "user_data", 3600)
    
    // Get value
    val, err := db.Get(ctx, "session:123")
    
    // Delete key
    deleted, err := db.Delete(ctx, "session:123")

    // Ensure the store is closed properly on application exit
    defer func() {
        if err := db.Close(); err != nil {
            log.Printf("Error while closing Hermes store: %v\n", err)
        }
    }()
}

STORE Documentation

Transaction Management

// Start transaction
tx := db.Transaction()

// Add operations
tx.Set(ctx, "account:1", 1000, 0)
tx.Incr(ctx, "account:1")
tx.Decr(ctx, "account:1")

// Commit transaction
if err := tx.Commit(); err != nil {
    // Handle error and rollback
    tx.Rollback()
}

TRANSACTION Documentation

Pub/Sub System

// Subscribe to channel
messages := db.Subscribe("updates")

// Receive messages
go func() {
    for msg := range messages {
        fmt.Println("Received update:", msg)
    }
}()

// Unsubscribe when done
db.Unsubscribe("updates", messages)

PUBSUB Documentation

Benchmarks

Performance tested on a single-core execution using Go's testing and runtime packages.

Operation Ops Count Time (sec) RPS (req/sec)
Get 100,000 0.15 675,328
Set 100,000 0.24 421,841

️ Test environment: 1 CPU core, TTL disabled, logging disabled.

Performance Characteristics

Operation Time Complexity Lock Type Notes
Get O(1) RLock Read-only access
Set/Delete O(1) Lock Full mutex lock
List operations O(1) Lock Head/tail ops for lists
Pub/Sub O(n) RLock n = number of subscribers
TTL Updates O(1) Lock Time complexity for map access

Performance Notes

  • Thread Safety: All operations protected by RWMutex
  • Memory Management: Automatic expired key cleanup
  • Batched Operations: Efficient flush implementation
  • Non-Blocking: Pub/Sub uses buffered channels

Important Notes:

  • Always use context for timeout/cancellation control
  • Close Pub/Sub channels when no longer needed
  • Transactions must be explicitly committed
  • Default channel buffer size: 10000 messages

License

MIT License. See LICENSE for full text.


Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrKeyNotFound          = errors.New("key not found")
	ErrKeyExpired           = errors.New("key expired")
	ErrKeyExists            = errors.New("key already exists")
	ErrInvalidType          = errors.New("invalid data type")
	ErrValueMismatch        = errors.New("value mismatch")
	ErrInvalidValueType     = errors.New("invalid value type")
	ErrContextCanceled      = errors.New("operation canceled")
	ErrInvalidTTL           = errors.New("invalid TTL value")
	ErrEmptyList            = errors.New("list is empty")
	ErrEmptyValues          = errors.New("empty value")
	ErrInvalidKey           = errors.New("invalid key")
	ErrTransactionNotActive = errors.New("transaction is not active")
	ErrTransactionFailed    = errors.New("transaction failed")
)

Functions

func BenchmarkParallelGet

func BenchmarkParallelGet()

func BenchmarkParallelSet

func BenchmarkParallelSet()

func IsContextCanceled

func IsContextCanceled(err error) bool

func IsEmptyList

func IsEmptyList(err error) bool

func IsInvalidKey

func IsInvalidKey(err error) bool

func IsInvalidTTL

func IsInvalidTTL(err error) bool

func IsInvalidType

func IsInvalidType(err error) bool

func IsInvalidValueType

func IsInvalidValueType(err error) bool

func IsKeyExists

func IsKeyExists(err error) bool

func IsKeyExpired

func IsKeyExpired(err error) bool

func IsKeyNotFound

func IsKeyNotFound(err error) bool

func IsTransactionFailed

func IsTransactionFailed(err error) bool

func IsTransactionNotActive

func IsTransactionNotActive(err error) bool

func IsValueMismatch

func IsValueMismatch(err error) bool

Types

type APIHandler

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

func NewAPIHandler

func NewAPIHandler(ctx context.Context, db contracts.StoreHandler) *APIHandler

func (*APIHandler) CloseAllSubscriptionsHandler

func (h *APIHandler) CloseAllSubscriptionsHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) DecrHandler

func (h *APIHandler) DecrHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) DeleteHandler

func (h *APIHandler) DeleteHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) DropAllHandler

func (h *APIHandler) DropAllHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) ExistsHandler

func (h *APIHandler) ExistsHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) FindByValueHandler

func (h *APIHandler) FindByValueHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) GetHandler

func (h *APIHandler) GetHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) GetSetHandler

func (h *APIHandler) GetSetHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) GetWithDetailsHandler

func (h *APIHandler) GetWithDetailsHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) HDelHandler

func (h *APIHandler) HDelHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) HExistsHandler

func (h *APIHandler) HExistsHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) HGetAllHandler

func (h *APIHandler) HGetAllHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) HGetHandler

func (h *APIHandler) HGetHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) HLenHandler

func (h *APIHandler) HLenHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) HSetHandler

func (h *APIHandler) HSetHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) IncrHandler

func (h *APIHandler) IncrHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) LLenHandler

func (h *APIHandler) LLenHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) LPopHandler

func (h *APIHandler) LPopHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) LPushHandler

func (h *APIHandler) LPushHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) LRangeHandler

func (h *APIHandler) LRangeHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) ListSubscriptionsHandler

func (h *APIHandler) ListSubscriptionsHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) RPopHandler

func (h *APIHandler) RPopHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) RPushHandler

func (h *APIHandler) RPushHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) RenameHandler

func (h *APIHandler) RenameHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) RunServer

func (h *APIHandler) RunServer(port, prefix string, middlewares ...func(http.Handler) http.Handler)

func (*APIHandler) SetCASHandler

func (h *APIHandler) SetCASHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) SetHandler

func (h *APIHandler) SetHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) SetNXHandler

func (h *APIHandler) SetNXHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) SetXXHandler

func (h *APIHandler) SetXXHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) SubscribeHandler

func (h *APIHandler) SubscribeHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) TypeHandler

func (h *APIHandler) TypeHandler(w http.ResponseWriter, r *http.Request)

func (*APIHandler) UpdateTTLHandler

func (h *APIHandler) UpdateTTLHandler(w http.ResponseWriter, r *http.Request)

type CommandAPI

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

func NewCommandAPI

func NewCommandAPI(db contracts.StoreHandler) *CommandAPI

func (*CommandAPI) Execute

func (c *CommandAPI) Execute(ctx context.Context, parts []string) (string, error)

type Config

type Config struct {
	ShardCount       int
	CleanupInterval  time.Duration
	EnableLogging    bool
	LogFile          string
	LogBufferSize    int
	MinLevel         logger.LogLevel
	PubSubBufferSize int
}

type DB

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

func NewStore

func NewStore(config Config) *DB

func (*DB) Close

func (db *DB) Close() error

func (*DB) CloseAllSubscriptionsForKey

func (db *DB) CloseAllSubscriptionsForKey(key string)

func (*DB) Commands

func (db *DB) Commands() contracts.CommandsHandler

func (*DB) Decr

func (db *DB) Decr(ctx context.Context, key string) (int64, error)

func (*DB) Delete

func (db *DB) Delete(ctx context.Context, key string) error

func (*DB) DropAll

func (db *DB) DropAll(ctx context.Context) error

func (*DB) Exists

func (db *DB) Exists(ctx context.Context, key string) (bool, error)

func (*DB) FindByValue

func (db *DB) FindByValue(ctx context.Context, value interface{}) ([]string, error)

func (*DB) Get

func (db *DB) Get(ctx context.Context, key string) (interface{}, error)

func (*DB) GetSet

func (db *DB) GetSet(ctx context.Context, key string, newValue interface{}, ttl int) (interface{}, error)

func (*DB) GetWithDetails

func (db *DB) GetWithDetails(ctx context.Context, key string) (interface{}, int, error)

func (*DB) HDel

func (db *DB) HDel(ctx context.Context, key string, field string) error

func (*DB) HExists

func (db *DB) HExists(ctx context.Context, key string, field string) (bool, error)

func (*DB) HGet

func (db *DB) HGet(ctx context.Context, key string, field string) (interface{}, error)

func (*DB) HGetAll

func (db *DB) HGetAll(ctx context.Context, key string) (map[string]interface{}, error)

func (*DB) HLen

func (db *DB) HLen(ctx context.Context, key string) (int, error)

func (*DB) HSet

func (db *DB) HSet(ctx context.Context, key string, field string, value interface{}, ttl int) error

func (*DB) Incr

func (db *DB) Incr(ctx context.Context, key string) (int64, error)

func (*DB) LLen

func (db *DB) LLen(ctx context.Context, key string) (int, error)

func (*DB) LPop

func (db *DB) LPop(ctx context.Context, key string) (interface{}, error)

func (*DB) LPush

func (db *DB) LPush(ctx context.Context, key string, values ...interface{}) error

func (*DB) LRange

func (db *DB) LRange(ctx context.Context, key string, start, end int) ([]interface{}, error)

func (*DB) ListSubscriptions

func (db *DB) ListSubscriptions() []string

func (*DB) Logger

func (db *DB) Logger() contracts.LoggerHandler

func (*DB) RPop

func (db *DB) RPop(ctx context.Context, key string) (interface{}, error)

func (*DB) RPush

func (db *DB) RPush(ctx context.Context, key string, values ...interface{}) error

func (*DB) Rename

func (db *DB) Rename(ctx context.Context, oldKey, newKey string) error

func (*DB) Set

func (db *DB) Set(ctx context.Context, key string, value interface{}, ttl int) error

func (*DB) SetCAS

func (db *DB) SetCAS(ctx context.Context, key string, oldValue, newValue interface{}, ttl int) error

func (*DB) SetNX

func (db *DB) SetNX(ctx context.Context, key string, value interface{}, ttl int) (bool, error)

func (*DB) SetXX

func (db *DB) SetXX(ctx context.Context, key string, value interface{}, ttl int) (bool, error)

func (*DB) Subscribe

func (db *DB) Subscribe(key string) chan string

func (*DB) Transaction

func (db *DB) Transaction() contracts.TransactionHandler

func (*DB) Type

func (db *DB) Type(ctx context.Context, key string) (interface{}, error)

func (*DB) Unsubscribe

func (db *DB) Unsubscribe(key string, ch chan string)

func (*DB) UpdateTTL

func (db *DB) UpdateTTL(ctx context.Context, key string, ttl int) error

type DataType

type DataType int
const (
	String DataType = iota
	List
	Hash
)

type Entry

type Entry struct {
	Value      interface{}
	Type       DataType
	Expiration time.Time
}

type Transaction

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

func NewTransaction

func NewTransaction(db contracts.StoreHandler) *Transaction

func (*Transaction) Commit

func (t *Transaction) Commit() error

func (*Transaction) Decr

func (t *Transaction) Decr(ctx context.Context, key string) error

func (*Transaction) Delete

func (t *Transaction) Delete(ctx context.Context, key string) error

func (*Transaction) Exists

func (t *Transaction) Exists(ctx context.Context, key string) (bool, error)

func (*Transaction) FindByValue

func (t *Transaction) FindByValue(ctx context.Context, value interface{}) ([]string, error)

func (*Transaction) Get

func (t *Transaction) Get(ctx context.Context, key string) (interface{}, error)

func (*Transaction) GetSet

func (t *Transaction) GetSet(ctx context.Context, key string, newValue interface{}, ttl int) (interface{}, error)

func (*Transaction) GetWithDetails

func (t *Transaction) GetWithDetails(ctx context.Context, key string) (interface{}, int, error)

func (*Transaction) HDel

func (t *Transaction) HDel(ctx context.Context, key, field string) error

func (*Transaction) HExists

func (t *Transaction) HExists(ctx context.Context, key, field string) (bool, error)

func (*Transaction) HGet

func (t *Transaction) HGet(ctx context.Context, key, field string) (interface{}, error)

func (*Transaction) HGetAll

func (t *Transaction) HGetAll(ctx context.Context, key string) (map[string]interface{}, error)

func (*Transaction) HLen

func (t *Transaction) HLen(ctx context.Context, key string) (int, error)

func (*Transaction) HSet

func (t *Transaction) HSet(ctx context.Context, key, field string, value interface{}, ttl int) error

func (*Transaction) Incr

func (t *Transaction) Incr(ctx context.Context, key string) error

func (*Transaction) LLen

func (t *Transaction) LLen(ctx context.Context, key string) (int, error)

func (*Transaction) LPop

func (t *Transaction) LPop(ctx context.Context, key string) (interface{}, error)

func (*Transaction) LPush

func (t *Transaction) LPush(ctx context.Context, key string, values ...interface{}) error

func (*Transaction) LRange

func (t *Transaction) LRange(ctx context.Context, key string, start, end int) ([]interface{}, error)

func (*Transaction) RPop

func (t *Transaction) RPop(ctx context.Context, key string) (interface{}, error)

func (*Transaction) RPush

func (t *Transaction) RPush(ctx context.Context, key string, values ...interface{}) error

func (*Transaction) Rename

func (t *Transaction) Rename(ctx context.Context, oldKey, newKey string) error

func (*Transaction) Rollback

func (t *Transaction) Rollback() error

func (*Transaction) Set

func (t *Transaction) Set(ctx context.Context, key string, value interface{}, ttl int) error

func (*Transaction) SetCAS

func (t *Transaction) SetCAS(ctx context.Context, key string, oldValue, newValue interface{}, ttl int) error

func (*Transaction) SetNX

func (t *Transaction) SetNX(ctx context.Context, key string, value interface{}, ttl int) error

func (*Transaction) SetXX

func (t *Transaction) SetXX(ctx context.Context, key string, value interface{}, ttl int) error

func (*Transaction) Type

func (t *Transaction) Type(ctx context.Context, key string) (interface{}, error)

func (*Transaction) UpdateTTL

func (t *Transaction) UpdateTTL(ctx context.Context, key string, ttl int) error

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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