persistvar

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Nov 26, 2025 License: MIT Imports: 5 Imported by: 0

README ¶

PersistVar

Go library for typed persistent variables with generic support (Var[T]) and multiple storage backends.

Currently supports:

  • FileStorage: lightweight storage, one file per variable.
  • BoltStorage: fast embedded storage, safe for concurrency and many variables.

📂 Project Structure

persistvar/
│
├── storage/
│   ├── filestorage.go       # File-based persistence
│   └── boltstorage.go       # BoltDB-based persistence
│
├── var.go                   # Generic implementation of Var[T]
├── manager.go               # VarManager with AutoSync and Close()
├── storage.go               # Storage interface { Save, Load, Close }
├── go.mod
└── README.md

📜 Usage Example

package main

import (
    "context"
    "fmt"
    "github.com/eos175/persistvar"
    "github.com/eos175/persistvar/storage"
    "time"
)

func main() {
    // FileStorage
    fs, _ := storage.NewFileStorage("persistent")
    // BoltStorage
    // boltStorage, _ := storage.NewBoltStorage("vars.db")

    mgr := persistvar.NewVarManager(fs)
    defer mgr.Close() // Saves pending changes and closes the manager on exit

    // Start autosync every 33 seconds
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    mgr.AutoSync(ctx, 33*time.Second)

    // Create persistent variables
    counter, _ := persistvar.NewVar(mgr, "counter", 0)
    username, _ := persistvar.NewVar(mgr, "username", "anon")

    // Modify variables
    counter.SetLazy(counter.Get() + 1)
    username.SetLazy("Emmanuel")

    fmt.Println("Counter:", counter.Get())
    fmt.Println("Username:", username.Get())

    // Wait to simulate work
    time.Sleep(10 * time.Second)
}

✅ Advantages

  • Go Generics → Var[T] is compile-time safe.
  • SetLazy() and global Sync() → full control over when changes are persisted.
  • AutoSync → automatically saves lazy changes in the background.
  • FileStorage → ultra-lightweight for a few variables.
  • BoltStorage → fast, concurrent, and reliable for many variables.
  • Minimalist and without unnecessary dependencies (only bbolt).

âš¡ Usage Recommendations

  1. Use FileStorage for a few simple variables.
  2. Use BoltStorage for many variables or when you need safe concurrency.
  3. Always combine AutoSync with defer mgr.Close() to ensure all pending changes are saved on exit.
ctx, cancel := context.WithCancel(context.Background())
mgr.AutoSync(ctx, 5*time.Second)
defer mgr.Close()   // final commit + resource cleanup
defer cancel()     // stop autosync

🔹 Conceptual Diagram

classDiagram
    class VarManager {
        -Storage storage
        -Var[T][] vars
        +AutoSync(ctx context.Context, interval time.Duration)
        +Sync() error
        +Close() error
    }

    class Var~T~ {
        -string key
        -T value
        -bool dirty
        +Key() string
        +Set(newValue T)
        +SetLazy(newValue T)
        +Sync() error
    }

    class Storage {
        <<interface>>
        +Save(key string, value []bytes) error
        +Load(key: string) []bytes, error
        +Close() error
    }

    class FileStorage {
        -[key].var
    }

    class BoltStorage {
        -bbolt.DB
    }

    VarManager --> Storage
    VarManager --> Var
    Storage <|-- FileStorage
    Storage <|-- BoltStorage

Documentation ¶

Index ¶

Constants ¶

This section is empty.

Variables ¶

This section is empty.

Functions ¶

This section is empty.

Types ¶

type Storage ¶

type Storage interface {
	// Save writes a new value for a given key.
	// It includes the oldValue for potential optimistic locking or Compare-And-Swap (CAS) like operations,
	// allowing implementations to prevent overwrites if the value has changed since it was last read.
	Save(key string, newValue []byte, oldValue []byte) error
	// Load retrieves the value associated with a key.
	// Returns an error if the key does not exist.
	Load(key string) ([]byte, error)
	// Delete removes a key-value pair from the storage.
	Delete(key string) error
	// Close releases any resources held by the storage backend.
	Close() error
}

Storage defines the interface for persistent storage backends. Implementations must ensure thread-safety where applicable for their storage mechanisms.

type Var ¶

type Var[T any] struct {
	// contains filtered or unexported fields
}

Var is a generic variable that persists its value to storage.

func NewVar ¶

func NewVar[T any](m *VarManager, key string, defaultValue T) (*Var[T], error)

NewVar creates or retrieves a managed persistent variable. If a Var with the given key already exists, the existing instance is returned. Otherwise, a new Var is initialized with defaultValue.

Important: For the same key, NewVar always returns the identical *Var[T] instance.

func (*Var[T]) Get ¶

func (v *Var[T]) Get() T

Get returns the current value.

func (*Var[T]) Key ¶

func (v *Var[T]) Key() string

Key returns the unique identifier for this variable.

func (*Var[T]) Set ¶

func (v *Var[T]) Set(newValue T) error

Set updates the value and immediately writes it to storage.

func (*Var[T]) SetLazy ¶

func (v *Var[T]) SetLazy(newValue T)

SetLazy updates the value in memory only. The change will be written to storage during the next Sync or background save.

func (*Var[T]) Sync ¶

func (v *Var[T]) Sync() error

Sync forces a write to storage if there are pending changes.

func (*Var[T]) Update ¶ added in v0.3.0

func (v *Var[T]) Update(transform func(T) (T, bool)) (T, error)

Update atomically modifies the value and immediately writes to storage if changed. Returns the new value and any storage error.

func (*Var[T]) UpdateLazy ¶ added in v0.3.0

func (v *Var[T]) UpdateLazy(transform func(T) (T, bool)) T

UpdateLazy atomically modifies the value in memory using the transform function. Returns the new value. If 'changed' is false, no update occurs.

type VarManager ¶

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

VarManager manages a collection of persistent variables, providing lifecycle and synchronization mechanisms.

func NewVarManager ¶

func NewVarManager(storage Storage) *VarManager

NewVarManager creates a new manager for persistent variables, using the provided storage backend.

func (*VarManager) AutoSync ¶

func (m *VarManager) AutoSync(ctx context.Context, interval time.Duration)

AutoSync starts a goroutine that periodically saves all lazy variables to storage. It returns immediately if AutoSync is already running.

func (*VarManager) Close ¶

func (m *VarManager) Close() error

Close gracefully shuts down the manager, ensuring all pending changes are written to storage and stopping any active AutoSync routine.

func (*VarManager) StopAutoSync ¶

func (m *VarManager) StopAutoSync()

StopAutoSync halts the automatic synchronization process.

func (*VarManager) Sync ¶

func (m *VarManager) Sync() error

Sync forces all managed variables to write their pending changes to storage immediately.

Directories ¶

Path Synopsis

Jump to

Keyboard shortcuts

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