modelcache

package
v0.8.3 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package modelcache provides a CachingModelStore decorator that memoizes LOCKED model descriptors. Correctness rests on the catalog invariants (commutativity + validation-monotonicity from internal/domain/model/schema) plus the validator-path refresh-on- stale in internal/domain/entity/handler.go; gossip invalidation and the TTL lease are performance/hygiene layers. See docs/superpowers/specs/2026-04-20-model-schema-extensions-design.md §4.5.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DecodeInvalidation

func DecodeInvalidation(raw []byte) (tenantID string, ref spi.ModelRef, ok bool)

DecodeInvalidation is the inverse. Returns ok=false on malformed input or any blank field so the gossip handler drops it silently.

func EncodeInvalidation

func EncodeInvalidation(tenantID string, ref spi.ModelRef) ([]byte, error)

EncodeInvalidation produces the payload sent on topicModelInvalidate.

Types

type CachingModelStore

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

CachingModelStore wraps an spi.ModelStore. Zero-value not safe — use New.

func New

func New(inner spi.ModelStore, broadcaster spi.ClusterBroadcaster, clk Clock, lease time.Duration) *CachingModelStore

New constructs a CachingModelStore.

broadcaster may be nil for single-node deployments — invalidation then only fires locally.

clock may be nil to use the wall clock.

lease must be > 0; actual expiry is jittered ±10% to prevent the cross-node herd that a uniform lease would produce.

func (*CachingModelStore) Delete

func (c *CachingModelStore) Delete(ctx context.Context, ref spi.ModelRef) error

func (*CachingModelStore) EntryExpiresAt

func (c *CachingModelStore) EntryExpiresAt(ref spi.ModelRef) time.Time

EntryExpiresAt is test-only introspection for the jitter-band check. Returns the zero time if no entry is cached for ref in any tenant.

func (*CachingModelStore) ExtendSchema

func (c *CachingModelStore) ExtendSchema(ctx context.Context, ref spi.ModelRef, delta spi.SchemaDelta) error

func (*CachingModelStore) Get

func (*CachingModelStore) GetAll

func (c *CachingModelStore) GetAll(ctx context.Context) ([]spi.ModelRef, error)

func (*CachingModelStore) IsLocked

func (c *CachingModelStore) IsLocked(ctx context.Context, ref spi.ModelRef) (bool, error)

func (*CachingModelStore) Lock

func (c *CachingModelStore) Lock(ctx context.Context, ref spi.ModelRef) error

func (*CachingModelStore) RefreshAndGet

func (c *CachingModelStore) RefreshAndGet(ctx context.Context, ref spi.ModelRef) (*spi.ModelDescriptor, error)

RefreshAndGet forces a cache miss, collapses concurrent callers via singleflight, then reads from the inner store and repopulates the cache. Used by the validator refresh-on-stale path.

func (*CachingModelStore) Save

func (*CachingModelStore) SetChangeLevel

func (c *CachingModelStore) SetChangeLevel(ctx context.Context, ref spi.ModelRef, level spi.ChangeLevel) error

func (*CachingModelStore) SubscribeLocal added in v0.7.0

func (c *CachingModelStore) SubscribeLocal(h func(tenant string, ref spi.ModelRef))

SubscribeLocal registers an in-process invalidation handler. The handler fires for every invalidation seen by this store — originating from a local mutation (Save/Lock/Unlock/SetChangeLevel/ Delete/ExtendSchema) AND from gossip events received from peer nodes. Downstream caches keyed off the same (tenant, ref) tuple (e.g. the path-validation negative cache) use this to stay in lock step with the descriptor cache regardless of cluster topology.

Issue #174 — pre-fix the path-validation cache subscribed to the gossip broadcaster directly, so single-node deployments (where the broadcaster is nil) never received any invalidation events.

func (*CachingModelStore) Unlock

func (c *CachingModelStore) Unlock(ctx context.Context, ref spi.ModelRef) error

type CachingStoreFactory

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

CachingStoreFactory wraps an spi.StoreFactory so that ModelStore(ctx) returns a per-request store whose Get / RefreshAndGet calls route through a single shared cache. All other factory methods pass through to the inner factory unchanged.

The cache is gossip-aware: mutations on a peer node evict the local entry via the "model.invalidate" topic. The ±10% jittered TTL is the fallback when gossip drops a message.

func NewCachingStoreFactory

func NewCachingStoreFactory(
	inner spi.StoreFactory,
	broadcaster spi.ClusterBroadcaster,
	clk Clock,
	lease time.Duration,
) *CachingStoreFactory

NewCachingStoreFactory wraps inner. broadcaster may be nil for single-node deployments. clk may be nil to use the wall clock. lease must be > 0.

func (*CachingStoreFactory) AsyncSearchStore

func (f *CachingStoreFactory) AsyncSearchStore(ctx context.Context) (spi.AsyncSearchStore, error)

func (*CachingStoreFactory) Close

func (f *CachingStoreFactory) Close() error

func (*CachingStoreFactory) EntityStore

func (f *CachingStoreFactory) EntityStore(ctx context.Context) (spi.EntityStore, error)

func (*CachingStoreFactory) KeyValueStore

func (f *CachingStoreFactory) KeyValueStore(ctx context.Context) (spi.KeyValueStore, error)

func (*CachingStoreFactory) MessageStore

func (f *CachingStoreFactory) MessageStore(ctx context.Context) (spi.MessageStore, error)

func (*CachingStoreFactory) ModelStore

func (f *CachingStoreFactory) ModelStore(ctx context.Context) (spi.ModelStore, error)

ModelStore returns a per-request store that reads through the shared cache and delegates mutations to the inner per-tenant store.

func (*CachingStoreFactory) ScheduledTaskStore added in v0.8.3

func (f *CachingStoreFactory) ScheduledTaskStore(ctx context.Context) (spi.ScheduledTaskStore, error)

func (*CachingStoreFactory) StateMachineAuditStore

func (f *CachingStoreFactory) StateMachineAuditStore(ctx context.Context) (spi.StateMachineAuditStore, error)

func (*CachingStoreFactory) SubscribeLocal added in v0.7.0

func (f *CachingStoreFactory) SubscribeLocal(h func(tenant string, ref spi.ModelRef))

SubscribeLocal registers an in-process invalidation handler on the shared CachingModelStore. The handler receives (tenant, ref) for every model invalidation — local mutations and gossip-received events alike. Downstream caches use this to stay in lock step regardless of cluster topology (issue #174).

func (*CachingStoreFactory) SupportsCompositeUniqueKeys added in v0.8.2

func (f *CachingStoreFactory) SupportsCompositeUniqueKeys() bool

SupportsCompositeUniqueKeys forwards the optional capability check to the inner factory. Returns false if the inner factory does not implement spi.CompositeUniqueKeyCapable.

func (*CachingStoreFactory) TransactionManager

func (f *CachingStoreFactory) TransactionManager(ctx context.Context) (spi.TransactionManager, error)

func (*CachingStoreFactory) WorkflowStore

func (f *CachingStoreFactory) WorkflowStore(ctx context.Context) (spi.WorkflowStore, error)

type Clock

type Clock interface {
	Now() time.Time
}

Clock abstracts time.Now so tests can drive expiry deterministically.

Jump to

Keyboard shortcuts

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