Skip to content

Cached Aggregate Store

A cached aggregate store wraps an existing aggregate store and loads and saves aggregates using a cache.

Aggregate caching reduces the frequency with which aggregates must be loaded from persistence. This can significantly improve performance, especially for workloads that involve frequent loading of aggregates, such as in stream processing applications.

Usage

A cached aggregate store requires an inner aggregate store (to defer to when hydrating aggregates) and an aggregate cache (to load and save cached aggregates).

import (
    "context"

    "github.com/allegro/bigcache/v3"
    "github.com/go-estoria/estoria/aggregatestore"
    "github.com/go-estoria/estoria-contrib/bigcache/aggregatecache"
)

func main() {
    // create an aggregate store
    store, _ := aggregatestore.New(eventStore, "thing", NewThing)

    // create an aggregate cache over a cache backend
    backend, _ := bigcache.New(context.Background(), bigcache.DefaultConfig(time.Minute))
    cache := aggregatecache.New[Thing](backend)

    // wrap an aggregate store with caching capabilities
    cachedStore, _ := aggregatestore.NewCachedStore(store, cache)
}

Aggregate Caches

While the cached aggregate store is a core Estoria component, it relies on an aggregate cache implementation to provide the actual caching functionality. See Aggregate Cache Implementations in the component library for more information on available aggregate cache implementations.

Custom Cache Implementations

Anything implementing the following interface can be used as an aggregate cache with Estoria:

type AggregateCache[S any] interface {
	GetAggregate(ctx context.Context, aggregateID typeid.ID) (*aggregatestore.CachedAggregate[S], error)
	PutAggregate(ctx context.Context, aggregateID typeid.ID, entry aggregatestore.CachedAggregate[S]) error
}

A cache stores and returns CachedAggregate[S] entries — a {State, Version} value — rather than aggregates. The cached store composes the aggregate itself from a hit, so a cache never needs to construct one. Returning nil, nil from GetAggregate signals a cache miss.