store

package
v0.0.0-...-ac6d57d Latest Latest
Warning

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

Go to latest
Published: Aug 18, 2022 License: MIT Imports: 4 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Memory

type Memory struct {
	sync.WaitGroup
	sync.RWMutex
	// contains filtered or unexported fields
}

Memory implements an in-memory key/value store with integer autoincrement keys and delayed writes. Internally uses a map for data storage instead of a slice for different reasons:

  • Ease of implementation (deterministic index)
  • Memory allocation time is predictable
  • Future proofing (deletes)

Slices and channels would be the straight forward, solution but implementation has a lot of caveats:

  • When waiting time.Sleep inside goroutines is non deterministic, scheduler might finish a routine faster and thus append in the wrong order. This can be solved by tracking the size of the slice and grow on demand, runtime should be responsible for this, not the developer.
  • Working with buffered channels means, ideally, the write to the channel is done inside a select clause with a default statement to avoid blocking, I would personally use this approach if latency was unpredictable or we want to have a limit on pending writes, but we have fixed delay and the sync.WaitGroup can easily be customized to achieve a similar limiter functionality.
  • If deletes become a requirement, slices just fall way behind in terms of performance due to memory management.

The benefits of slices do not outweight the added complexity go maps have O(1) amortized complexity for insert and lookups on finite space domains (integer), making them performant.

func NewMemory

func NewMemory(delay time.Duration) *Memory

NewMemory creates a new store with 'delay' writes. It is useful to allow the caller to setup the delay, specially for testing as we avoid mocking.

func (*Memory) Close

func (m *Memory) Close() error

Close blocks until all pending write operations are done Useful if data would be persisted, otherwise just a nice "to have" in case other implementations are done.

func (*Memory) Get

func (m *Memory) Get(id int) ([]byte, error)

Get returns the value at index id or an error otherwise

func (*Memory) Set

func (m *Memory) Set(value []byte) (int, error)

Set saves the value and returns the index where data will be written after delay. It does not block but fires a routine and keeps track of it via sync.WaitGroup, it uses atomic increase on the index, and a sync.Mutex when writing on a map for memory safety (concurrency).

type Store

type Store interface {
	Get(int) ([]byte, error)
	Set([]byte) (int, error)
	Close() error
}

Store defines an interface for a store of any byte slice that tracks the elements with an integer id in incremental fashion. Close is added as it is a common practice for other non-trivial implementations to perform tear down processes like graceful shutdown.

Jump to

Keyboard shortcuts

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