structr

package module
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Apr 25, 2024 License: MIT Imports: 12 Imported by: 0

README

go-structr

A library with a series of performant data types with automated struct value indexing. Indexing is supported via arbitrary combinations of fields, and in the case of the cache type, negative results (errors!) are also supported.

Under the hood, go-structr maintains a hashmap per index, where each hashmap is a hashmap keyed by serialized input key type. This is handled by the incredibly performant serialization library go-mangler, which at this point in time supports just about any arbitrary type, so feel free to index by anything!

Cache example

type Cached struct {
    Username    string
    Domain      string
    URL         string
    CountryCode int
}

var c structr.Cache[*Cached]

c.Init(structr.CacheConfig[*Cached]{

    // Fields this cached struct type
    // will be indexed and stored under.
    Indices: []structr.IndexConfig{
        {Fields: "Username,Domain", AllowZero: true},
        {Fields: "URL"},
        {Fields: "CountryCode", Multiple: true},
    },

    // Maximum LRU cache size before
    // new entries cause evictions.
    MaxSize: 1000,

    // User provided value copy function to
    // reduce need for reflection + ensure
    // concurrency safety for returned values.
    Copy: func(c *Cached) *Cached {
        c2 := new(Cached)
        *c2 = *c
        return c2
    },

    // User defined invalidation hook.
    Invalidate: func(c *Cached) {
        log.Println("invalidated:", c)
    },
})

// Access and store indexes ahead-of-time for perf.
usernameDomainIndex := c.Index("Username,Domain")
urlIndex := c.Index("URL")
countryCodeIndex := c.Index("CountryCode")

var url string

// Generate URL index key.
urlKey := urlIndex.Key(url)

// Load value from cache, with callback function to hydrate
// cache if value cannot be found under index name with key.
// Negative (error) results are also cached, with user definable
// errors to ignore from caching (e.g. context deadline errs).
value, err := c.LoadOne(urlIndex, func() (*Cached, error) {
    return dbType.SelectByURL(url)
}, urlKey)
if err != nil {
    return nil, err
}

// Store value in cache, only if provided callback
// function returns without error. Passes value through
// invalidation hook regardless of error return value.
//
// On success value will be automatically added to and
// accessible under all initially configured indices.
if err := c.Store(value, func() error {
    return dbType.Insert(value)
}); err != nil {
    return nil, err
}

// Generate country code index key.
countryCodeKey := countryCodeIndex.Key(42)

// Invalidate all cached results stored under
// provided index name with give field value(s).
c.Invalidate(countryCodeIndex, countryCodeKey)

Queue example


type Queued struct{
    Username    string
    Domain      string
    URL         string
    CountryCode int
}

var q structr.Queue[*Queued]

q.Init(structr.QueueConfig[*Cached]{

    // Fields this queued struct type
    // will be indexed and stored under.
    Indices: []structr.IndexConfig{
        {Fields: "Username,Domain", AllowZero: true},
        {Fields: "URL"},
        {Fields: "CountryCode", Multiple: true},
    },

    // User defined pop hook.
    Pop: func(c *Cached) {
        log.Println("popped:", c)
    },
})

// Access and store indexes ahead-of-time for perf.
usernameDomainIndex := q.Index("Username,Domain")
urlIndex := q.Index("URL")
countryCodeIndex := q.Index("CountryCode")

// ...
q.PushBack(Queued{
    Username:   "billybob",
    Domain:     "google.com",
    URL:        "https://some.website.here",
    CountryCode: 42,
})

// ...
queued, ok := q.PopFront()

// Generate country code index key.
countryCodeKey := countryCodeIndex.Key(42)

// ...
queuedByCountry := q.Pop(countryCodeIndex, countryCodeKey)

Notes

This is a core underpinning of GoToSocial's performance.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultIgnoreErr

func DefaultIgnoreErr(err error) bool

DefaultIgnoreErr is the default function used to ignore (i.e. not cache) incoming error results during Load() calls. By default ignores context pkg errors.

Types

type Cache

type Cache[StructType any] struct {
	// contains filtered or unexported fields
}

Cache provides a structure cache with automated indexing and lookups by any initialization-defined combination of fields. This also supports caching of negative results (errors!) returned by LoadOne().

func (*Cache[T]) Cap

func (c *Cache[T]) Cap() int

Cap returns the maximum capacity (size) of cache.

func (*Cache[T]) Clear

func (c *Cache[T]) Clear()

Clear empties the cache by calling .Trim(0).

func (*Cache[T]) Get

func (c *Cache[T]) Get(index *Index, keys ...Key) []T

Get fetches values from the cache stored under index, using precalculated index keys.

func (*Cache[T]) GetOne

func (c *Cache[T]) GetOne(index *Index, key Key) (T, bool)

GetOne fetches value from cache stored under index, using precalculated index key.

func (*Cache[T]) Index

func (c *Cache[T]) Index(name string) *Index

Index selects index with given name from cache, else panics.

func (*Cache[T]) Init

func (c *Cache[T]) Init(config CacheConfig[T])

Init initializes the cache with given configuration including struct fields to index, and necessary fns.

func (*Cache[T]) Invalidate

func (c *Cache[T]) Invalidate(index *Index, keys ...Key)

Invalidate invalidates all results stored under index keys.

func (*Cache[T]) Len

func (c *Cache[T]) Len() int

Len returns the current length of cache.

func (*Cache[T]) Load

func (c *Cache[T]) Load(index *Index, keys []Key, load func([]Key) ([]T, error)) ([]T, error)

Load fetches values from the cache stored under index, using precalculated index keys. The cache will attempt to results with values stored under keys, passing keys with uncached results to the provider load callback to further hydrate the cache with missing results. Cached error results not included or returned by this function.

func (*Cache[T]) LoadOne

func (c *Cache[T]) LoadOne(index *Index, key Key, load func() (T, error)) (T, error)

LoadOneBy fetches one result from the cache stored under index, using precalculated index key. In the case that no result is found, provided load callback will be used to hydrate the cache.

func (*Cache[T]) Put

func (c *Cache[T]) Put(values ...T)

Put will insert the given values into cache, calling any invalidate hook on each value.

func (*Cache[T]) Store

func (c *Cache[T]) Store(value T, store func() error) error

Store will call the given store callback, on non-error then passing the provided value to the Put() function. On error return the value is still passed to stored invalidate hook.

func (*Cache[T]) Trim

func (c *Cache[T]) Trim(perc float64)

Trim will truncate the cache to ensure it stays within given percentage of MaxSize.

type CacheConfig added in v0.6.0

type CacheConfig[StructType any] struct {

	// Indices defines indices to create
	// in the Cache for the receiving
	// generic struct type parameter.
	Indices []IndexConfig

	// MaxSize defines the maximum number
	// of items allowed in the Cache at
	// one time, before old items start
	// getting evicted.
	MaxSize int

	// IgnoreErr defines which errors to
	// ignore (i.e. not cache) returned
	// from load function callback calls.
	// This may be left as nil, on which
	// DefaultIgnoreErr will be used.
	IgnoreErr func(error) bool

	// Copy provides a means of copying
	// cached values, to ensure returned values
	// do not share memory with those in cache.
	Copy func(StructType) StructType

	// Invalidate is called when cache values
	// (NOT errors) are invalidated, either
	// as the values passed to Put() / Store(),
	// or by the keys by calls to Invalidate().
	Invalidate func(StructType)
}

CacheConfig defines config vars for initializing a struct cache.

type Index

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

Index is an exposed Cache internal model, used to extract struct keys, generate hash checksums for them and store struct results by the init defined config. This model is exposed to provide faster lookups in the case that you would like to manually provide the used index via the Cache.___By() series of functions, or access the underlying index key generator.

func (*Index) Key added in v0.3.0

func (i *Index) Key(parts ...any) Key

Key generates Key{} from given parts for the type of lookup this Index uses in cache. NOTE: panics on incorrect no. parts / types given.

func (*Index) Keys added in v0.6.0

func (i *Index) Keys(parts ...[]any) []Key

Keys generates []Key{} from given (multiple) parts for the type of lookup this Index uses in the cache. NOTE: panics on incorrect no. parts / types given.

func (*Index) Name added in v0.5.0

func (i *Index) Name() string

Name returns the receiving Index name.

type IndexConfig

type IndexConfig struct {

	// Fields should contain a comma-separated
	// list of struct fields used when generating
	// keys for this index. Nested fields should
	// be specified using periods. An example:
	// "Username,Favorites.Color"
	//
	// Note that nested fields where the nested
	// struct field is a ptr are supported, but
	// nil ptr values in nesting will result in
	// that particular value NOT being indexed.
	// e.g. with "Favorites.Color" if *Favorites
	// is nil then it will not be indexed.
	//
	// Field types supported include any of those
	// supported by the `go-mangler` library.
	Fields string

	// Multiple indicates whether to accept multiple
	// possible values for any single index key. The
	// default behaviour is to only accept one value
	// and overwrite existing on any write operation.
	Multiple bool

	// AllowZero indicates whether to accept zero
	// value fields in index keys. i.e. whether to
	// index structs for this set of field values
	// IF any one of those field values is the zero
	// value for that type. The default behaviour
	// is to skip indexing structs for this lookup
	// when any of the indexing fields are zero.
	AllowZero bool
}

IndexConfig defines config variables for initializing a struct index.

type Key added in v0.5.0

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

Key represents one key to lookup (potentially) stored entries in an Index.

func (Key) Equal added in v0.5.0

func (k Key) Equal(o Key) bool

Equal returns whether keys are equal.

func (Key) Key added in v0.6.0

func (k Key) Key() string

Key returns the underlying cache key string. NOTE: this will not be log output friendly.

func (Key) Values added in v0.5.0

func (k Key) Values() []any

Value returns the raw slice of values that comprise this Key.

func (Key) Zero added in v0.5.0

func (k Key) Zero() bool

Zero indicates a zero value key.

type Queue added in v0.6.0

type Queue[StructType any] struct {
	// contains filtered or unexported fields
}

Queue provides a structure model queue with automated indexing and popping by any init defined lookups of field combinations.

func (*Queue[T]) Index added in v0.6.0

func (q *Queue[T]) Index(name string) *Index

Index selects index with given name from queue, else panics.

func (*Queue[T]) Init added in v0.6.0

func (q *Queue[T]) Init(config QueueConfig[T])

Init initializes the queue with given configuration including struct fields to index, and necessary fns.

func (*Queue[T]) Len added in v0.6.0

func (q *Queue[T]) Len() int

Len returns the current length of queue.

func (*Queue[T]) MoveBack added in v0.6.0

func (q *Queue[T]) MoveBack(index *Index, keys ...Key)

MoveBack attempts to move values indexed under any of keys to the back of the queue.

func (*Queue[T]) MoveFront added in v0.6.0

func (q *Queue[T]) MoveFront(index *Index, keys ...Key)

MoveFront attempts to move values indexed under any of keys to the front of the queue.

func (*Queue[T]) Pop added in v0.6.0

func (q *Queue[T]) Pop(index *Index, keys ...Key) []T

Pop attempts to pop values from queue indexed under any of keys.

func (*Queue[T]) PopBack added in v0.6.0

func (q *Queue[T]) PopBack() (T, bool)

PopBack pops the current value at back of the queue.

func (*Queue[T]) PopBackN added in v0.6.0

func (q *Queue[T]) PopBackN(n int) []T

PopBackN attempts to pop n values from back of the queue.

func (*Queue[T]) PopFront added in v0.6.0

func (q *Queue[T]) PopFront() (T, bool)

PopFront pops the current value at front of the queue.

func (*Queue[T]) PopFrontN added in v0.6.0

func (q *Queue[T]) PopFrontN(n int) []T

PopFrontN attempts to pop n values from front of the queue.

func (*Queue[T]) PushBack added in v0.6.0

func (q *Queue[T]) PushBack(values ...T)

PushBack pushes values to back of queue.

func (*Queue[T]) PushFront added in v0.6.0

func (q *Queue[T]) PushFront(values ...T)

PushFront pushes values to front of queue.

type QueueConfig added in v0.6.0

type QueueConfig[StructType any] struct {

	// Indices defines indices to create
	// in the Queue for the receiving
	// generic struct parameter type.
	Indices []IndexConfig

	// Pop is called when queue values
	// are popped, during calls to any
	// of the Pop___() series of fns.
	Pop func(StructType)
}

QueueConfig defines config vars for initializing a struct queue.

type QueueCtx added in v0.7.0

type QueueCtx[StructType any] struct {
	Queue[StructType]
	// contains filtered or unexported fields
}

QueueCtx is a context-aware form of Queue{}.

func (*QueueCtx[T]) PopBack added in v0.7.0

func (q *QueueCtx[T]) PopBack(ctx context.Context) (T, bool)

PopBack pops the current value at back of the queue, else blocking on ctx.

func (*QueueCtx[T]) PopFront added in v0.7.0

func (q *QueueCtx[T]) PopFront(ctx context.Context) (T, bool)

PopFront pops the current value at front of the queue, else blocking on ctx.

func (*QueueCtx[T]) PushBack added in v0.7.0

func (q *QueueCtx[T]) PushBack(values ...T)

PushBack pushes values to back of queue.

func (*QueueCtx[T]) PushFront added in v0.7.0

func (q *QueueCtx[T]) PushFront(values ...T)

PushFront pushes values to front of queue.

func (*QueueCtx[T]) Wait added in v0.7.0

func (q *QueueCtx[T]) Wait() <-chan struct{}

Wait returns a ptr to the current ctx channel, this will block until next push to the queue.

Jump to

Keyboard shortcuts

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