scale

package
v0.28.0 Latest Latest
Warning

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

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

Documentation

Overview

Package scale provides fetch-seam scale-out primitives: [Fetcher → Fetcher] decorators that any embedder's query engine composes over fetch.Fetcher (a per-tenant engine, a cluster fan-out, a cross-tenant fetch.Merge) without the library owning a query language.

  • SplitFetcher splits a wide time window into aligned sub-intervals fetched in parallel, the query-frontend "split by interval" technique applied to the fetch contract.
  • CacheFetcher memoizes results of fully-pushable (serializable-equality) requests.

Both implement fetch.Fetcher, so they nest freely — e.g. a SplitFetcher over a CacheFetcher over a cluster fetcher caches each aligned sub-window independently.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cache

type Cache interface {
	Get(key string) ([]*fetch.Batch, bool)
	Put(key string, batches []*fetch.Batch)
}

Cache stores fetch results keyed by an opaque string (built by the CacheFetcher from the request's tenant, window, and equality specs). Implementations must be safe for concurrent use. MemoryCache is the built-in bounded-LRU implementation.

Stored batches are treated as immutable snapshots: a CacheFetcher hands the cache an independent copy on Put, and callers of Get must not mutate the returned batches' sample columns in place (they may freely reslice/reorder the returned slice).

type CacheFetcher

type CacheFetcher struct {
	Inner fetch.Fetcher
	Cache Cache

	// Freshness is the recent-window guard in nanoseconds: a request whose End is within
	// Freshness of now is not cached. 0 ⇒ no guard (every cacheable request is cached).
	Freshness int64

	// Now returns the current time as unix nanoseconds, for the Freshness guard. nil ⇒
	// [time.Now]. Tests inject a fixed clock.
	Now func() int64
}

CacheFetcher memoizes the results of **fully-pushable** requests: a request is cacheable only when every matcher carries a serializable equality fetch.EqualMatcher spec, so the cache key is exact and a hit can never drop a matching series. Requests with a non-equality matcher (an opaque predicate that cannot be keyed) bypass the cache and hit Inner directly.

The results cache does not auto-invalidate, so a request touching the **recent** window — where new samples may still arrive — must not be cached. The Freshness guard enforces that: a request whose window ends within Freshness of now bypasses the cache. Composed under a SplitFetcher, this caches the settled sub-windows and always re-fetches the most recent one (the standard query-frontend behavior).

func (CacheFetcher) Fetch

Fetch returns the cached batches for r when present, otherwise fetches from Inner and stores the result. A non-cacheable request (or a nil Cache) is a transparent pass-through to Inner.

func (CacheFetcher) Unwrap added in v0.17.0

func (f CacheFetcher) Unwrap() fetch.Fetcher

Unwrap exposes the cached fetcher so fetch.CounterOf can reach the engine's Count for the count() pushdown (count is not cached — it reads through to Inner).

type MemoryCache

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

MemoryCache is a bounded, LRU Cache held entirely in memory. It is safe for concurrent use. On Put it stores a deep copy of the batches (independent of the producer's reused buffers); on Get it returns a fresh slice of those snapshots so a caller's reslicing never disturbs the cache's order.

func NewMemoryCache

func NewMemoryCache(maxEntries int) *MemoryCache

NewMemoryCache returns an LRU cache holding at most maxEntries results (≤ 0 ⇒ unbounded).

func (*MemoryCache) Get

func (c *MemoryCache) Get(key string) ([]*fetch.Batch, bool)

Get returns a fresh slice of the cached batches and marks the entry most-recently-used.

func (*MemoryCache) Len

func (c *MemoryCache) Len() int

Len returns the number of cached entries (testing/introspection).

func (*MemoryCache) Put

func (c *MemoryCache) Put(key string, batches []*fetch.Batch)

Put stores a deep copy of batches under key, evicting the least-recently-used entry when the cache exceeds its bound.

type SplitFetcher

type SplitFetcher struct {
	Inner    fetch.Fetcher
	Interval int64 // sub-window width in nanos; ≤ 0 disables splitting (transparent pass-through)
}

SplitFetcher fetches a fetch.Request as a set of aligned sub-windows of width Interval, run concurrently against Inner and merged by series. Splitting on a fixed grid (aligned to multiples of Interval) makes each sub-window's bounds independent of the overall request, so overlapping queries reuse the same sub-windows — the property a downstream CacheFetcher relies on for hits across shifting ranges.

func (SplitFetcher) Fetch

Fetch splits r's window into aligned sub-windows, fetches them concurrently from Inner, and returns their merged batches. A request spanning a single sub-window (or with Interval ≤ 0) passes straight through, so splitting never adds overhead to a narrow query.

func (SplitFetcher) Unwrap added in v0.17.0

func (f SplitFetcher) Unwrap() fetch.Fetcher

Unwrap exposes the split fetcher's inner so fetch.CounterOf can reach the engine's Count for the count() pushdown: count is evaluated over the full [Start, End] on Inner directly (a count is not a split-friendly aggregate — a series active in two sub-windows counts once for the whole range, so summing per-window counts would over-count).

Jump to

Keyboard shortcuts

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