duramap

package module
v0.0.0-...-444af41 Latest Latest
Warning

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

Go to latest
Published: Feb 10, 2020 License: MIT Imports: 8 Imported by: 1

README

Duramap

GoDoc Build Status codecov

Duramap wraps the speed of a map[string]interface{} with the safety of a sync.RWMutex and the durability of bbolt (effectively, it is an always-fully-loaded write-through cache). It is intended to be a reliable thread-safe store of mutable data with fast read requirements.

The internal map cuts most of the cost (~18ms on my machine) of accessing K/V items through BoltDB directly, while serialization of map values adds minimal overhead to writes (values are encoded with vmihailenco/msgpack). See Benchmarks below for more details.

New and improved!

The old Duramap used to serialize the entire map contents with MsgPack and store this in a single key, with mutation happening directly to the map passed to UpdateMap. Now, the new Duramap now serializes individual key values and writes each to their own corresponding key in bbolt, saving drastically on write overhead for non-tiny maps. Updates now happen through a new Tx struct.

Usage

See GoDoc for full docs. Example:

package mypackage

import (
	"testing"

	"github.com/notduncansmith/duramap"
)

func TestRoundtrip(t *testing.T) {
	dm, err := duramap.NewDuramap("./example.db", "example")

	if err != nil {
		t.Errorf("Should be able to open database: %v", err)
		return
	}

	if err = dm.Load(); err != nil {
		t.Errorf("Should be able to load map: %v", err)
		return
	}

	err = dm.UpdateMap(func(tx *Tx) error {
		tx.Set("foo", "bar")
		if tx.Get("foo") != "bar" {
			t.Error("Should be able to read saved value")
		}
		return nil
	})

	if err != nil {
		t.Errorf("Should be able to save value: %v", err)
	}

	foo := dm.WithMap(func(m GenericMap) interface{} {
		// this is the internal map, do not mutate it!
		return m["foo"]
	}).(string)

	if foo != "bar" {
		t.Error("Should be able to read saved value")
		return
	}
}

Benchmarks

goos: darwin
goarch: amd64
pkg: github.com/notduncansmith/duramap
BenchmarkReadsDuramap/int64-12  	17755630	        57.6 ns/op
BenchmarkReadsDuramap/str64b-12 	18237058	        56.9 ns/op
BenchmarkReadsDuramap/str128b-12         	19252372	        56.2 ns/op
BenchmarkReadsDuramap/str256b-12         	20408672	        54.7 ns/op
BenchmarkWritesDuramap/int64-12          	      63	  19229244 ns/op
BenchmarkWritesDuramap/str64b-12         	      66	  18821763 ns/op
BenchmarkWritesDuramap/str128b-12        	      63	  19051516 ns/op
BenchmarkWritesDuramap/str256b-12        	      63	  18178327 ns/op
BenchmarkReadsBbolt/str256b-12           	      64	  18297425 ns/op
BenchmarkWritesBbolt/str256b-12          	      63	  19110888 ns/op
BenchmarkReadsRWMap/rwmutex-12           	75495019	        15.7 ns/op
BenchmarkWritesRWMap/rwmutex-12          	34192036	        34.3 ns/op
BenchmarkReadsMutableMap/mutable-12      	29584789	        39.0 ns/op
BenchmarkWritesMutableMap/mutable-12     	21703112	        54.3 ns/op

License

Released under The MIT License (see LICENSE.txt).

Copyright 2019 Duncan Smith

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Duramap

type Duramap struct {
	Path string
	Name string
	// contains filtered or unexported fields
}

Duramap is a map of strings to ambiguous data structures, which is protected by a Read/Write mutex and backed by a bbolt database

func NewDuramap

func NewDuramap(path, name string, secret EncryptionSecret) (*Duramap, error)

NewDuramap returns a new Duramap backed by a bbolt database located at `path`

func (*Duramap) DoWithMap

func (dm *Duramap) DoWithMap(f func(m GenericMap))

DoWithMap is like `WithMap` but does not return a result

func (*Duramap) Load

func (dm *Duramap) Load() error

Load reads the stored Duramap value and sets it

func (*Duramap) Truncate

func (dm *Duramap) Truncate() error

Truncate will reset the contents of the Duramap to an empty GenericMap

func (*Duramap) UpdateMap

func (dm *Duramap) UpdateMap(f func(tx *Tx) error) error

UpdateMap is like `DoWithMap` but the result of `f` is re-saved afterwards

func (*Duramap) WithMap

func (dm *Duramap) WithMap(f func(m GenericMap) interface{}) interface{}

WithMap returns the result of calling `f` with the internal map

type EncryptionSecret

type EncryptionSecret = *[32]byte

EncryptionSecret is a 32-byte secret key used to encrypt data with the Secretbox construction

type GenericMap

type GenericMap = map[string]interface{}

GenericMap is a map of strings to empty interfaces

type Tx

type Tx struct {
	M *GenericMap
	// contains filtered or unexported fields
}

Tx is a transaction that operates on a Duramap. It has a reference to the internal map.

func (*Tx) Get

func (tx *Tx) Get(k string) interface{}

Get returns the latest value either written in the Tx or stored in the map

func (*Tx) Set

func (tx *Tx) Set(k string, v interface{})

Set writes a new value in the Tx

Jump to

Keyboard shortcuts

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