state

package module
v0.0.0-...-205f043 Latest Latest
Warning

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

Go to latest
Published: Jun 5, 2023 License: MIT Imports: 21 Imported by: 0

README

go-state

A way of caching Go types to disk

Documentation

Overview

Example

This example shows the basics on how to use the go-state module:

  1. It first initialises a Blueprint for our State instance
  2. Then it creates a new State from the Blueprint by using the LoadNewest function
  3. It then shows how to add values to the CachedField(s) of the State
  4. We then showcase how the State can be saved to disk then retrieved in a new State instance by using LoadNewest
  5. Finally, we show how to fetch values from a CachedField within the loaded State
// Create the Blueprint for our State instances:
//
// Blueprint's store the information on where to save a State to disk. State's are saved to timestamped directories,
// the time format can be customised by passing implementations to Blueprint.SetBaseDir and Blueprint.SetIsBaseDir.
// This is useful when needing to continue from the latest saved State.
const customBaseDirFormat = "people-02-01-2006T15-04"
blueprint := NewBlueprint(
	Map[string, string]("name_to_address", JSON),
	Map[string, time.Time]("name_to_birthday", JSON),
	Map[int, string]("person_priority", JSON),
).SetBaseDir(func(state State) string {
	return state.CreatedAt().Format(customBaseDirFormat)
}).SetIsBaseDir(func(info os.FileInfo) (time.Time, bool) {
	t, err := time.Parse(customBaseDirFormat, info.Name())
	return t, err == nil
})
state := New(blueprint)

fmt.Println("Empty state:")
fmt.Println(state)

state.MustSet("name_to_address", "13 Nelson St", "John S")
state.MustSet("name_to_address", "93 Heath Rd", "Alice K")

state.MustSet(
	"name_to_birthday",
	time.Date(1972, 1, 27, 0, 0, 0, 0, time.UTC), "John S",
)
state.MustSet(
	"name_to_birthday",
	time.Date(2000, 6, 26, 0, 0, 0, 0, time.UTC), "Alice K",
)

state.MustSet("person_priority", "Alice K", 1)
state.MustSet("person_priority", "John S", 2)

fmt.Println()
fmt.Println("Filled state:")
fmt.Println(state)

state = nil

var err error
if state, err = LoadNewest(blueprint); err != nil {
	fmt.Printf("Could not load State from Blueprint: %v\n", err)
}
defer state.Delete()

fmt.Println()
fmt.Println("Loaded state:")
fmt.Println(state)

fmt.Println()
const aliceKey = "Alice K"
aliceAddress := state.MustGet("name_to_address", aliceKey)
fmt.Printf("The address of %s is %s\n", aliceKey, aliceAddress)
Output:

Empty state:
name_to_address = map[]
name_to_birthday = map[]
person_priority = map[]

Filled state:
name_to_address = map[Alice K:93 Heath Rd, John S:13 Nelson St]
name_to_birthday = map[Alice K:2000-06-26 00:00:00 +0000 UTC, John S:1972-01-27 00:00:00 +0000 UTC]
person_priority = map[1:Alice K, 2:John S]

Loaded state:
name_to_address = map[Alice K:93 Heath Rd, John S:13 Nelson St]
name_to_birthday = map[Alice K:2000-06-26 00:00:00 +0000 UTC, John S:1972-01-27 00:00:00 +0000 UTC]
person_priority = map[1:Alice K, 2:John S]

The address of Alice K is 93 Heath Rd

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultBaseDir

func DefaultBaseDir(state State) string

func DefaultBlueprintFilename

func DefaultBlueprintFilename(old string) string

func DefaultIsBaseDir

func DefaultIsBaseDir(info os.FileInfo) (time.Time, bool)

func DefaultIsBlueprintFilenameFunc

func DefaultIsBlueprintFilenameFunc(filename string) bool

func DefaultNow

func DefaultNow() time.Time

func DefaultString

func DefaultString(state State) string

Types

type BaseDirFunc

type BaseDirFunc func(state State) string

type Blueprint

type Blueprint interface {
	SetBaseDir(baseDir BaseDirFunc) Blueprint
	IsBaseDir(info os.FileInfo) (time.Time, bool)
	SetIsBaseDir(isBD IsBaseDirFunc) Blueprint
	SetString(string StringFunc) Blueprint
	Now() time.Time
	SetNow(now NowFunc) Blueprint
	SetBlueprintFilename(bpFnFunc BlueprintFilenameFunc) Blueprint
	IsBlueprintFilename(filename string) bool
	SetIsBlueprintFilename(isBPFn IsBlueprintFilenameFunc) Blueprint
	// Fields returns the names of all the fields within the Blueprint, except from the field holding the Blueprint
	// itself.
	Fields() []string
	json.Marshaler
	json.Unmarshaler
	CachedField
}

func NewBlueprint

func NewBlueprint(fields ...CachedField) Blueprint

type BlueprintFilenameFunc

type BlueprintFilenameFunc func(old string) string

type CachedField

type CachedField interface {
	Name() string
	Encoding() EncodingType
	Set(state StateWriter, value any, components ...any) error
	Get(state StateReader, components ...any) (any, error)
	Make() CachedField
}

CachedField represents a field in stateProto that can be cached on-disk using the PathsToBytesDirectory lookup.

func Map

func Map[K comparable, V any](name string, encoding EncodingType) CachedField

type CachedFieldIterator

type CachedFieldIterator interface {
	// Continue checks whether the CachedFieldIterator has not finished. I.e. there are still more elements to iterate over.
	Continue() bool
	// I will return the current i (index) value.
	I() int
	// Components will return the key components for the current element that can be passed to CachedField.Get to
	// retrieve it.
	Components() []any
	// Get will return the current element that is being iterated over.
	Get() (any, error)
	// Next should be called at the end of each loop to retrieve the next element.
	Next() error
	// Field will return the IterableCachedField that this CachedFieldIterator is iterating over.
	Field() IterableCachedField
	// Len returns the length of the CachedFieldIterator.
	Len() int
}

func MergeCachedFieldIterators

func MergeCachedFieldIterators(iterators ...CachedFieldIterator) CachedFieldIterator

type CachedFieldStringer

type CachedFieldStringer interface {
	String(state StateReader) string
}

type EncodingType

type EncodingType string
const (
	JSON EncodingType = ".json"
	Gob  EncodingType = ".bin"
)

func (EncodingType) Ext

func (et EncodingType) Ext() string

Ext returns the appropriate file extension for the given EncodingType.

func (EncodingType) String

func (et EncodingType) String() string

type FS

type FS interface {
	Exists(name string) bool
}

type FSReadWriter

type FSReadWriter interface {
	FSReader
	FSWriter
}

func DirFS

func DirFS(dir string) FSReadWriter

type FSReader

type FSReader interface {
	FS
	fs.FS
}

type FSWriteCloser

type FSWriteCloser interface {
	FSWriter
	io.Closer
}

func ZipFS

func ZipFS() FSWriteCloser

type FSWriter

type FSWriter interface {
	FS
	// WriteFile writes the given data with the given permissions to a file relative to the FSWriter.
	WriteFile(name string, data []byte, perms os.FileMode) error
	// MkdirAll creates all the directories required to
	MkdirAll(path string, perm os.FileMode) error
}

type IsBaseDirFunc

type IsBaseDirFunc func(info os.FileInfo) (time.Time, bool)

type IsBlueprintFilenameFunc

type IsBlueprintFilenameFunc func(filename string) bool

type IterableCachedField

type IterableCachedField interface {
	CachedField
	// Iter returns the CachedFieldIterator that can be used to iterate over the instance of the CachedField itself.
	Iter(state StateReader) (CachedFieldIterator, error)
	// Merge will perform a union/update procedure between the referred to IterableCachedField and the given
	// CachedField.
	Merge(mergeTo StateWriter, mergeFrom StateReader, fieldToMerge IterableCachedField) error
}

IterableCachedField represents a field in stateProto that can be cached, but also can be iterated through using the CachedFieldIterator.

type NowFunc

type NowFunc func() time.Time

type ScoutStateManager

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

ScoutStateManager manages the reads/writes to and from a stateProto instance. It provides synchronisation across all goroutines that use a single stateProto via a sync.RWMutex.

type State

type State interface {
	// BaseDir returns the directory that the State will Save to.
	//
	// By default, if no override is set within the Blueprint, this is DefaultBaseDir.
	BaseDir() string
	// CreatedAt returns when the State was created.
	//
	// This is the first time that the State was saved to disk. State's that exist only in memory will return a zero
	// time.Time.
	CreatedAt() time.Time
	// Blueprint returns the Blueprint for the State.
	Blueprint() Blueprint
	// Get calls CachedField.Get on the CachedField with the given name.
	Get(fieldName string, components ...any) (any, error)
	// MustGet calls CachedField.Get on the CachedField with the given name, and panics if an error occurs.
	MustGet(fieldName string, components ...any) any
	// Set calls CachedField.Set on the CachedField with the given name.
	Set(fieldName string, value any, components ...any) error
	// MustSet calls CachedField.Set on the CachedField with the given name, and panics if an error occurs.
	MustSet(fieldName string, value any, components ...any)
	// Iter calls IterableCachedField.Iter on the IterableCachedField with the given name.
	Iter(fieldName string) (CachedFieldIterator, error)
	// MustIter calls IterableCachedField.Iter on the IterableCachedField with the given name, and panics if an error
	// occurs.
	MustIter(fieldName string) CachedFieldIterator
	// GetCachedField returns the CachedField of the given name.
	GetCachedField(fieldName string) CachedField
	// GetIterableCachedField returns the IterableCachedField of the given name.
	GetIterableCachedField(fieldName string) IterableCachedField
	// MergeIterableCachedFields merges the IterableCachedField(s) from the given State into the referred to State.
	MergeIterableCachedFields(stateToMerge State) error
	// Delete deletes the on-disk representation of the State. I.e. the directory residing at BaseDir.
	Delete()
	// String returns the string representation of the State.
	//
	// By default, if no override is set within the Blueprint, this is DefaultString.
	String() string
}

func Load

func Load(blueprint Blueprint, path string) (State, error)

Load will load the State at the given path with the given Blueprint.

func LoadNewest

func LoadNewest(blueprint Blueprint) (state State, err error)

LoadNewest will either create a new State with the given Blueprint or load the newest State in the current directory,

The newest State in the current directory is found by:

  1. Iterating over all files
  2. Checking if the filename can be parsed as a base directory for the Blueprint using the bound IsBaseDirFunc.
  3. Checking if State.Load can be called with no errors for the current file/dirFS. This filters out any
  4. Initialising the file/directory as a State of the Blueprint, then checking for the max State.CreatedAt in the current directory.

If a previous State is found in the current directory, then State.Load will automatically be called.

The time used when creating a new State is found by using Blueprint.Now.

func New

func New(blueprint Blueprint) State

New creates a new State in-memory using the given Blueprint. This State can then be saved to disk using State.Save.

If a State with the same Blueprint and the same State.BaseDir already exists on disk, then it will be deleted.

func StateInMemory

func StateInMemory(blueprint Blueprint) State

StateInMemory will create a stateProto that only exists in memory. Only the CachedField will be created and the stateProto.InMemory flag set.

type StateReadWriter

type StateReadWriter interface {
	StateReader
	StateWriter
}

type StateReader

type StateReader interface {
	FSReader() FSReader
}

type StateWriter

type StateWriter interface {
	FSWriter() FSWriter
}

type StringFunc

type StringFunc func(state State) string

Jump to

Keyboard shortcuts

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