cache

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jun 20, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package cache is fabriq's first-class caching port: a byte-level, scope-aware cache with per-keyspace freshness policy. It is pure (no driver imports): adapters/cache implements it over grove kv; fabriqtest provides FakeCache. Tenant/scope are derived EXCLUSIVELY from context — never caller-supplied.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Fingerprint

func Fingerprint(v any) (string, error)

Fingerprint is a stable content hash of a normalized query value (entity, filter, sort, limit, offset, or traversal spec). It is the cache key for query keyspaces. encoding/json sorts map keys, so logically-equal queries that differ only in map literal order produce the same fingerprint. Partition is NOT part of the fingerprint — it comes from the keyspace+ctx, so the same filter never collides across tenants or scopes.

Types

type Cache

type Cache interface {
	// GetOrLoad returns the cached value for key, or calls load exactly once
	// (single-flight per key) on a miss, stores the result under the keyspace
	// policy, and returns it.
	GetOrLoad(ctx context.Context, ks Keyspace, key string,
		load func(context.Context) ([]byte, error)) ([]byte, error)
	// Get returns the cached value; ok=false on miss.
	Get(ctx context.Context, ks Keyspace, key string) (val []byte, ok bool, err error)
	// Set stores a value under the keyspace policy.
	Set(ctx context.Context, ks Keyspace, key string, val []byte) error
	// Invalidate removes specific keys from the keyspace (targeted eviction).
	Invalidate(ctx context.Context, ks Keyspace, keys ...string) error
	// InvalidateKeyspace bumps the keyspace generation, orphaning every entry
	// under it in the current partition at once (no mass deletes).
	InvalidateKeyspace(ctx context.Context, ks Keyspace) error
	// InvalidateEntity bumps the generation of `entity` for the Global, Tenant,
	// and (if a scope is in context) TenantScope partitions — orphaning every
	// cached entry whose keyspace declares Entity == entity in those partitions.
	// This is the write-driven invalidation the command plane calls post-commit.
	InvalidateEntity(ctx context.Context, entity string) error
	// Close releases resources.
	Close() error
}

Cache is the byte-level caching port. Typed access is via Typed[T].

type Codec

type Codec interface {
	Encode(v any) ([]byte, error)
	Decode(data []byte, into any) error
}

Codec serializes typed values for Typed[T]. The byte-level Cache port is codec-agnostic; Typed[T] applies a codec at the edge.

type JSON

type JSON struct{}

JSON is the default codec.

func (JSON) Decode

func (JSON) Decode(data []byte, into any) error

func (JSON) Encode

func (JSON) Encode(v any) ([]byte, error)

type Keyspace

type Keyspace struct {
	Name      string
	Version   int
	Partition Partition
	Policy    Policy
	// Entity, when set, names the registry entity this keyspace caches reads
	// of. The generation is then keyed by entity, so a write to that entity
	// (via Cache.InvalidateEntity) orphans this keyspace. Empty for keyspaces
	// not tied to a single entity (their generation is keyed by Name).
	Entity string
}

Keyspace is a named family of cached values, declared once and reused. Version is a code-level epoch: bump it in source to invalidate on deploy.

type Mode

type Mode int

Mode is the per-keyspace invalidation mechanism (the precision seam).

const (
	// TTLOnly: bounded staleness, no active eviction.
	TTLOnly Mode = iota
	// Versioned: generation-bump invalidation (mass-orphan via InvalidateKeyspace;
	// in P2, auto-bumped per entity-type on write).
	Versioned
	// EventEvict: targeted per-id eviction. The cross-node consumer lands in P2;
	// in P1, explicit Invalidate(keys...) is the working path.
	EventEvict
)

type Partition

type Partition int

Partition is the isolation dimension declared per keyspace. The concrete tenant/scope is resolved from context, never passed by callers.

const (
	// Global is engine-wide: no tenant segment. Use for cross-tenant
	// reference data (schema descriptors, dynamic-entity defs).
	Global Partition = iota
	// Tenant isolates by the context tenant.
	Tenant
	// TenantScope isolates by tenant + scope_id (the feat/native-scope axis).
	TenantScope
)

func (Partition) Resolve

func (p Partition) Resolve(ctx context.Context) (string, error)

Resolve returns the key segment for this partition under ctx. Global never requires a tenant; Tenant/TenantScope require one (and error if absent).

type Policy

type Policy struct {
	Mode Mode
	TTL  time.Duration // required for TTLOnly; backstop otherwise (0 = no expiry)
}

Policy is a keyspace's freshness contract.

type Typed

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

Typed[T] is a type-safe view over a Cache + Keyspace, applying a Codec at the edge so callers work with T, not bytes. core stays codec-agnostic; the byte-level Cache is the transport.

func For

func For[T any](c Cache, ks Keyspace) Typed[T]

For builds a Typed[T] using the default JSON codec.

func (Typed[T]) GetOrLoad

func (t Typed[T]) GetOrLoad(ctx context.Context, key string,
	load func(context.Context) (T, error)) (T, error)

GetOrLoad returns the cached T, or calls load once on a miss, encodes and stores the result, and returns it.

Jump to

Keyboard shortcuts

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