Documentation
¶
Overview ¶
Package appendstore provides a high-performance append-only log storage engine with in-memory indexing, LRU caching, and secondary indexes.
Architecture:
- Append-only log file for durability
- In-memory primary index for O(1) key lookups
- LRU cache for frequently accessed entries
- Memory-mapped reads with a file-read fallback
- Optional secondary indexes over application-defined attributes
- Background compaction to reclaim deleted space
Thread Safety:
- All operations are thread-safe via RWMutex
- Reads can proceed concurrently
- Writes are serialized
- Open acquires an exclusive process lock for the database path
Durability:
- All writes are appended to the log immediately
- Index is rebuilt from log on startup (crash recovery)
- Optional periodic sync for fsync guarantees
Example ¶
package main
import (
"fmt"
"os"
"path/filepath"
"github.com/sirrobot01/appendstore"
)
func main() {
dir, err := os.MkdirTemp("", "appendstore-example-")
if err != nil {
panic(err)
}
defer os.RemoveAll(dir)
store, err := appendstore.Open(filepath.Join(dir, "example.db"), appendstore.Options{
IndexedFields: []string{"kind"},
})
if err != nil {
panic(err)
}
defer store.Close()
if err := store.Put("greeting", []byte("hello"), &appendstore.PutOptions{
Attributes: map[string]string{"kind": "message"},
}); err != nil {
panic(err)
}
value, err := store.Get("greeting")
if err != nil {
panic(err)
}
fmt.Println(string(value))
fmt.Println(store.KeysBy("kind", "message"))
}
Output: hello [greeting]
Index ¶
- Variables
- func Downgrade(src, dst string, options DowngradeOptions) error
- type DowngradeOptions
- type Metadata
- type MigrationInfo
- type Options
- type PutOptions
- type Stats
- type Store
- func (s *Store) AttributeValues(field string) []string
- func (s *Store) Close() error
- func (s *Store) Compact() error
- func (s *Store) CountBy(field, value string) int
- func (s *Store) Delete(key string) error
- func (s *Store) DiskSize() int64
- func (s *Store) Exists(key string) bool
- func (s *Store) ForEach(fn func(key string, value []byte) error) error
- func (s *Store) ForEachMetadata(fn func(key string, meta *Metadata) error) error
- func (s *Store) Get(key string) ([]byte, error)
- func (s *Store) GetMetadata(key string) (*Metadata, error)
- func (s *Store) Keys() []string
- func (s *Store) KeysBy(field, value string) []string
- func (s *Store) Len() int
- func (s *Store) MemoryUsage() int64
- func (s *Store) NeedsCompaction() bool
- func (s *Store) Put(key string, value []byte, options *PutOptions) error
- func (s *Store) ReadOnly() bool
- func (s *Store) Stats() Stats
- func (s *Store) Sync() error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrStoreClosed = errors.New("store is closed") ErrStoreLocked = errors.New("store is already open by another process") ErrCorruptedData = errors.New("corrupted data detected") ErrUnsupportedVersion = errors.New("unsupported log version") ErrUnsupportedFeature = errors.New("unsupported log feature") ErrReadOnly = errors.New("store is read-only") ErrCompactionInProgress = errors.New("compaction already in progress") ErrKeyNotFound = errors.New("key not found") ErrInvalidKey = errors.New("invalid key") ErrInvalidAttribute = errors.New("invalid attribute name") ErrValueTooLarge = errors.New("value too large") ErrAttributesTooLarge = errors.New("attributes too large") )
Common errors
Functions ¶
func Downgrade ¶ added in v0.6.0
func Downgrade(src, dst string, options DowngradeOptions) error
Downgrade writes the live contents of the log at src to a new log at dst in format version 3 or version 4. It is the way back for a caller that upgraded to version 5 and must run an older build again.
Downgrade fails, and leaves nothing at dst, when a record holds data the target format cannot express: an extension entry, an attribute version 3 has no field for, or a value too long for a version 3 field.
Downgrade reads src. It writes to src only to discard an incomplete trailing record from an interrupted write, which is the same repair Open performs.
This function exists for the transition described in docs/stable-format.md. It is removed together with the migration path when support for versions 1 to 4 ends.
Types ¶
type DowngradeOptions ¶ added in v0.6.0
type DowngradeOptions struct {
// Version is the target log format: 3 or 4.
Version uint32
// Overwrite replaces a destination that already exists. Without it,
// Downgrade refuses rather than replace a file it did not create. The
// replacement is still atomic: the output is renamed into place only after
// every record is written, so a failed run leaves the old file untouched.
Overwrite bool
}
DowngradeOptions configures Downgrade.
type Metadata ¶
Metadata is the application-defined metadata associated with a value. Its Attributes map is always a defensive copy owned by the caller.
type MigrationInfo ¶ added in v0.5.0
type MigrationInfo struct {
// Path is the store path being migrated.
Path string
// FromVersion is the format found on disk; ToVersion is what replaces it.
FromVersion, ToVersion uint32
// Backup is the copy of the original log, or "" when NoMigrationBackup is
// set. Report it: it is what a downgrade restores.
Backup string
}
MigrationInfo describes a log about to be rewritten in the current format.
type Options ¶
type Options struct {
// CacheSize is the maximum number of entries to cache (default: 1000)
CacheSize int
// SyncInterval controls automatic fsync behavior: 0 syncs every mutation,
// a positive duration syncs periodically, and a negative duration disables
// automatic syncing (including on Close). Sync can always be called explicitly.
SyncInterval time.Duration
// CompactionThreshold is the deleted entry ratio that triggers compaction (default: 0.2)
CompactionThreshold float64
// AutoCompact enables automatic background compaction
AutoCompact bool
// IndexedFields lists attribute names that should have in-memory secondary
// indexes. Only these fields can be queried with KeysBy efficiently.
IndexedFields []string
// OnError receives errors from background sync and compaction. It is never
// called while the store mutex is held.
OnError func(error)
// OnMigrate is called when Open finds a log in an older format, after the
// backup is taken and before the log is rewritten. Returning an error
// aborts Open and leaves the log in its original format. Optional.
OnMigrate func(MigrationInfo) error
// NoMigrationBackup skips the copy Open keeps of a pre-migration log.
// Migrating is one-way — a build that predates the new format refuses to
// read a migrated log — so only set this where the caller has its own way
// back, or where the disk cannot spare a second copy of the log.
NoMigrationBackup bool
}
Options configures a Store.
type PutOptions ¶
PutOptions describes application-defined metadata for a value.
type Stats ¶
type Stats struct {
Writes int64
Reads int64
CacheHits int64
CacheMisses int64
Deletes int64
Compactions int64
}
Stats is an instantaneous snapshot of operational counters. Reads counts every value returned by Get and ForEach, whether served from the cache or from disk; CacheHits and CacheMisses partition the Get calls.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is an append-only storage engine.
func (*Store) AttributeValues ¶
AttributeValues returns the sorted values present for an indexed field.
func (*Store) ForEach ¶
ForEach iterates over all entries in disk order (optimized for sequential I/O). The value passed to fn is owned by ForEach and only valid for the duration of that call — callers that retain it must copy.
Scans deliberately bypass the LRU cache: a full pass touches every entry once and never reuses them, so caching would evict the genuinely-hot working set (active streams) and replace it with single-use scan data. Each value is read under a short RLock so writers interleave between keys and reads observe the current log even across a compaction swap. A single reusable buffer keeps the scan allocation-free per record.
func (*Store) ForEachMetadata ¶
ForEachMetadata iterates over a snapshot of metadata only (no disk reads).
func (*Store) GetMetadata ¶
GetMetadata retrieves metadata without reading the full value. This is O(1) from the in-memory index - no disk access
func (*Store) MemoryUsage ¶
MemoryUsage returns approximate in-memory usage
func (*Store) NeedsCompaction ¶
NeedsCompaction returns true if compaction would reclaim significant space
func (*Store) Put ¶
func (s *Store) Put(key string, value []byte, options *PutOptions) error
Put stores a key-value pair with optional application-defined attributes.
func (*Store) ReadOnly ¶ added in v0.6.0
ReadOnly reports whether Open put the store in read-only mode because the log sets a read-only feature bit this build does not know. Every write then returns an error wrapping ErrReadOnly that names the feature.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
appendstore-downgrade
command
Command appendstore-downgrade writes an older log from an appendstore database.
|
Command appendstore-downgrade writes an older log from an appendstore database. |