record

package
v1.0.0-rc1.1-beta Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2022 License: MIT Imports: 14 Imported by: 0

README

Heirarchical Caching Data Model

The goals of the record package and the model generator are:

  1. Explicitly define a conceptual data model
  2. Generate types that mirror the conceptual data model
  3. Move caching into the data model

Conceptual Data Model

Entities

An entity is a record that is composed of a set of attributes. There are two basic categories of attributes: complex and simple. A complex attribute is one that itself has attributes, such as an entity or a chain. A simple attribute represents a single value or a simple collection of values. Since an attribute can be an entity, which itself has attributes, the data model is heirarchical.

Simple Attributes

Simple attributes are state or index attributes. A state attribute is considered to be part of the proper state of the entity, whereas index attributes exist soley to index other records.

Simple attributes can be atomic values, sets, or lists. Atomic values may themselves be structured, but they are persisted atomically so they are considered to be a single value by the CDM. Sets and lists are ordered and unordered collections of values, respectively.

Parameterized Attributes

An attribute of an entity may be parameterized. A parameterized attribute is effectively a map or dictionary where the key is a tuple of the parameters. For example, the root entity in a personnel database may have an attribute, Person, with the a string parameter, Name. accessed as model.Person(name).

Implementation

The generator produces a struct type for every entity, with a method for every attribute. The return type for a complex attribute is the corresponding entity struct type. The return type for a simple attribute is one of the simple attribute types defined in the record package. Parameterized attributes are backed by a map and single-valued attributes are backed by a simple field. The first time an attribute is accessed, an object of the appropriate type is created. Subsequent accesses will return the same object.

Example

The following is an example of a data model that could be used to track personnel.

- name: Model
  type: entity
  root: true
  attributes:
    - name: Person
      type: entity
      parameters:
        - name: Surname
          type: string
        - name: GivenName
          type: string
      attributes:
        - name: State
          type: state
          dataType: PersonState
          pointer: true
        - name: Dependents
          type: state
          dataType: string
          collection: set
type Model struct{...}

func (*Model) Person(surname, givenName string) *ModelPerson

type ModelPerson struct{...}

func (*ModelPerson) State() *record.Value[*PersonState]
func (*ModelPerson) Dependents() *record.Set[string]

Documentation

Index

Constants

This section is empty.

Variables

View Source
var BytesWrapper = &wrapperFuncs[[]byte]{
	copy:      func(v []byte) []byte { u := make([]byte, len(v)); copy(u, v); return u },
	marshal:   oldMarshal(encoding.BytesMarshalBinary),
	unmarshal: encoding.BytesUnmarshalBinary,
}

BytesWrapper defines un/marshalling functions for byte slice fields.

View Source
var HashWrapper = &wrapperFuncs[[32]byte]{
	copy:      copyValue[[32]byte],
	marshal:   oldMarshalPtr(encoding.ChainMarshalBinary),
	unmarshal: encoding.ChainUnmarshalBinary,
}

HashWrapper defines un/marshalling functions for hash fields.

View Source
var StringWrapper = &wrapperFuncs[string]{
	copy:      copyValue[string],
	marshal:   oldMarshal(encoding.StringMarshalBinary),
	unmarshal: encoding.StringUnmarshalBinary,
}

StringWrapper defines un/marshalling functions for string fields.

View Source
var TxidWrapper = &wrapperFuncs[*url.TxID]{
	copy:      copyRef[*url.TxID],
	marshal:   marshalAsString[*url.TxID],
	unmarshal: unmarshalFromString(url.ParseTxID),
}

TxidWrapper defines un/marshalling functions for txid fields.

View Source
var UintWrapper = &wrapperFuncs[uint64]{
	copy:      copyValue[uint64],
	marshal:   oldMarshal(encoding.UvarintMarshalBinary),
	unmarshal: encoding.UvarintUnmarshalBinary,
}

UintWrapper defines un/marshalling functions for uint fields.

View Source
var UrlWrapper = &wrapperFuncs[*url.URL]{
	copy:      copyRef[*url.URL],
	marshal:   marshalAsString[*url.URL],
	unmarshal: unmarshalFromString(url.Parse),
}

UrlWrapper defines un/marshalling functions for url fields.

Functions

func CompareHash

func CompareHash(u, v [32]byte) int

func CompareTxid

func CompareTxid(u, v *url.TxID) int

func CompareUrl

func CompareUrl(u, v *url.URL) int

func ParseString

func ParseString(s string) (string, error)

func Struct

func Struct[T any, PT ptrBinaryValue[T]]() encodableValue[PT]

Struct returns an encodable value for the given encodable struct-type.

func Union

func Union[T encoding.BinaryValue](unmarshal func([]byte) (T, error)) encodableValue[T]

Union returns an encodable value for the given encodable union type.

func UnionFactory

func UnionFactory[T encoding.BinaryValue](unmarshal func([]byte) (T, error)) func() encodableValue[T]

UnionFactory curries Union.

func Wrapped

func Wrapped[T any](funcs *wrapperFuncs[T]) encodableValue[T]

Wrapped returns an encodable value for the given type using the given wrapper functions.

func WrappedFactory

func WrappedFactory[T any](funcs *wrapperFuncs[T]) func() encodableValue[T]

WrappedFactory curries Wrapped.

Types

type Counted

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

Counted records an insertion-ordered list of values as separate records plus a record for the count.

func NewCounted

func NewCounted[T any](logger log.Logger, store Store, key Key, namefmt string, new func() encodableValue[T]) *Counted[T]

NewCounted returns a new Counted using the given encodable value type.

func (*Counted[T]) Commit

func (c *Counted[T]) Commit() error

Commit implements Record.Commit.

func (*Counted[T]) Count

func (c *Counted[T]) Count() (int, error)

Count loads the size of the list.

func (*Counted[T]) Get

func (c *Counted[T]) Get(i int) (T, error)

Get loads the I'th element of the list.

func (*Counted[T]) GetAll

func (c *Counted[T]) GetAll() ([]T, error)

GetAll loads all the elements of the list.

func (*Counted[T]) IsDirty

func (c *Counted[T]) IsDirty() bool

IsDirty implements Record.IsDirty.

func (*Counted[T]) Last

func (c *Counted[T]) Last() (int, T, error)

Last loads the value of the last element.

func (*Counted[T]) Put

func (c *Counted[T]) Put(v T) error

Put adds an element to the list.

func (*Counted[T]) Resolve

func (c *Counted[T]) Resolve(key Key) (Record, Key, error)

Resolve implements Record.Resolve.

type Key

type Key []interface{}

A Key is the key for a record.

func (Key) Append

func (k Key) Append(v ...interface{}) Key

Append creates a child key of this key.

func (Key) Hash

func (k Key) Hash() storage.Key

Hash converts the record key to a storage key.

func (Key) MarshalJSON

func (k Key) MarshalJSON() ([]byte, error)

MarshalJSON is implemented so keys are formatted nicely by zerolog.

func (Key) String

func (k Key) String() string

String returns a human-readable string for the key.

type KvStore

type KvStore struct {
	Store storage.KeyValueTxn
}

KvStore is a Store that reads/writes from/to a key-value store.

func (KvStore) GetValue

func (s KvStore) GetValue(key Key, value ValueWriter) error

GetValue loads the raw value and calls value.LoadBytes.

func (KvStore) PutValue

func (s KvStore) PutValue(key Key, value ValueReader) error

PutValue marshals the value and stores it.

type List

type List[T any] struct {
	Value[[]T]
}

List records an unordered list of values as a single record.

func NewList

func NewList[T any](logger log.Logger, store Store, key Key, namefmt string, encoder encodableValue[T]) *List[T]

NewList returns a new List using the given encoder and comparison.

func (*List[T]) Add

func (s *List[T]) Add(v ...T) error

Add inserts values into the set, sorted.

func (*List[T]) Commit

func (s *List[T]) Commit() error

Commit implements Record.Commit.

func (*List[T]) IsDirty

func (s *List[T]) IsDirty() bool

IsDirty implements Record.IsDirty.

type Record

type Record interface {
	// Resolve resolves the record or a child record.
	Resolve(key Key) (Record, Key, error)
	// IsDirty returns true if the record has been modified.
	IsDirty() bool
	// Commit writes any modifications to the store.
	Commit() error
}

A Record is a component of a data model.

type RecordPtr

type RecordPtr[T any] interface {
	*T
	Record
}

RecordPtr is satisfied by a type T where *T implements Record.

type Set

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

Set records an ordered list of values as a single record.

func NewSet

func NewSet[T any](logger log.Logger, store Store, key Key, namefmt string, encoder encodableValue[T], cmp func(u, v T) int) *Set[T]

NewSet returns a new Set using the given encoder and comparison.

func (*Set[T]) Add

func (s *Set[T]) Add(v ...T) error

Add inserts values into the set, sorted.

func (*Set[T]) Commit

func (s *Set[T]) Commit() error

Commit implements Record.Commit.

func (*Set[T]) Find

func (s *Set[T]) Find(v T) (T, error)

Find returns the matching value.

func (*Set[T]) Index

func (s *Set[T]) Index(v T) (int, error)

Index returns the index of the value.

func (*Set[T]) IsDirty

func (s *Set[T]) IsDirty() bool

IsDirty implements Record.IsDirty.

func (*Set[T]) Put

func (s *Set[T]) Put(u []T) error

Put stores the value, sorted.

func (*Set[T]) Remove

func (s *Set[T]) Remove(v T) error

Remove removes a value from the set.

type Store

type Store interface {
	// GetValue loads the value from the underlying store and writes it. Byte
	// stores call LoadBytes(data) and value stores call LoadValue(v, false).
	GetValue(key Key, value ValueWriter) error
	// PutValue gets the value from the reader and stores it. A byte store
	// marshals the value and stores the bytes. A value store finds the
	// appropriate value and calls LoadValue(v, true).
	PutValue(key Key, value ValueReader) error
}

A Store loads and stores values.

type Value

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

Value records a value.

func NewValue

func NewValue[T any](logger log.Logger, store Store, key Key, namefmt string, allowMissing bool, value encodableValue[T]) *Value[T]

NewValue returns a new Value using the given encodable value.

func (*Value[T]) Commit

func (v *Value[T]) Commit() error

Commit implements Record.Commit.

func (*Value[T]) Get

func (v *Value[T]) Get() (u T, err error)

Get loads the value, unmarshalling it if necessary.

func (*Value[T]) GetAs

func (v *Value[T]) GetAs(target interface{}) error

GetAs loads the value, coerces it to the target type, and assigns it to the target. The target must be a non-nil pointer to T.

func (*Value[T]) GetValue

func (v *Value[T]) GetValue() (encoding.BinaryValue, error)

GetValue loads the value.

func (*Value[T]) IsDirty

func (v *Value[T]) IsDirty() bool

IsDirty implements Record.IsDirty.

func (*Value[T]) Key

func (v *Value[T]) Key(i int) interface{}

Key returns the I'th component of the value's key.

func (*Value[T]) LoadBytes

func (v *Value[T]) LoadBytes(data []byte) error

LoadBytes unmarshals the value from bytes.

func (*Value[T]) LoadValue

func (v *Value[T]) LoadValue(value ValueReader, put bool) error

LoadValue sets the value from the reader. If put is false, the value will be copied. If put is true, the value will be marked dirty.

func (*Value[T]) Put

func (v *Value[T]) Put(u T) error

Put stores the value.

func (*Value[T]) Resolve

func (v *Value[T]) Resolve(key Key) (Record, Key, error)

Resolve implements Record.Resolve.

type ValueMarshaller

type ValueMarshaller[T any] func(value T) ([]byte, error)

type ValueReader

type ValueReader interface {
	// GetValue returns the value.
	GetValue() (encoding.BinaryValue, error)
}

A ValueReader holds a readable value.

type ValueUnmarshaller

type ValueUnmarshaller[T any] func(data []byte) (T, error)

type ValueWriter

type ValueWriter interface {
	// LoadValue stores the value of the reader into the receiver.
	LoadValue(value ValueReader, put bool) error
	// LoadBytes unmarshals a value from bytes into the receiver.
	LoadBytes(data []byte) error
}

A ValueWriter holds a writable value.

Jump to

Keyboard shortcuts

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