Skip to content
Query.Farm
Talk with Us

Cache control

On this page

Advertising a result as reusable by the client.

source
public static final class Builder

Description

Builder for CacheControl; see the class javadoc for field semantics.

Members

Builder ttl(int seconds)

Freshness lifetime in whole seconds, relative to full-result receipt.

Builder expires(String rfc3339Utc)

Absolute RFC 3339 UTC deadline; the lifetime is expires - now.

Builder scope(String scope)

Reuse scope.

Builder noStore(boolean noStore)

Explicit “never cache”; overrides any freshness key.

Builder etag(String etag)

Strong validator for conditional revalidation.

Builder lastModified(String rfc3339Utc)

Weaker RFC 3339 UTC validator; fallback when no ETag is advertised.

Builder revalidatable(boolean revalidatable)

Whether the worker can confirm freshness cheaply without recomputing; gates whether the client ever sends a conditional request.

Builder staleWhileRevalidate(int seconds)

Grace window to serve stale while revalidating in the background.

Builder staleIfError(int seconds)

Grace window to serve stale if a revalidation RPC fails.

Builder notModified(boolean notModified)

304-equivalent: set on a 0-row batch replying to a conditional request to assert the client’s stored payload is still fresh.

Builder partitionScope(boolean partitionScope)

Opt in to per-partition caching: on a SINGLE_VALUE_PARTITIONS function the client ADDITIONALLY stores the result split by partition value, so a later =/IN scan on the partition column(s) serves the requested partitions without calling the worker. Additive — the whole-scan entry is still stored and served.

Builder perValue(boolean perValue)

Opt in to per-value memoization: the client ADDITIONALLY memoizes each distinct worker-input tuple’s output, keyed on that tuple, so the same value is served without calling the worker on a later chunk or a later query. Only meaningful for an exchange-mode map — a scalar, or a blended table-in-out invoked through a correlated LATERAL.

Defaults off, and should stay off unless one call is genuinely expensive. A per-value serve is not free: it costs a key probe, a decode of the stored value and a row-assembly step, for every distinct value. That only pays back when it is cheaper than simply asking the worker. For a cheap arithmetic map it is a large net loss — the probe-and-assemble path measures roughly 50x the cost of the worker call it replaces. The engine cannot tell an expensive call from a cheap one, which is why this is an explicit advertisement rather than a heuristic: only the function author knows. Turn it on for a model inference, a geocode, or a rate-limited remote fetch, where one call dwarfs a cache probe.

Independent of whole-result cacheability: a function can be worth caching by ttl without per-value memoization paying off, and vice versa.

CacheControl build()

Validate and freeze.

source
public final class CacheControl

Description

Result-cache control metadata (vgi.cache.*) advertised by a table function on the first data batch it emits.

The vocabulary mirrors HTTP caching (RFC 9111/9110): a freshness lifetime (Builder#ttl/Builder#expires), a reuse Builder#scope, validators (Builder#etag / Builder#lastModified) for conditional revalidation, and stale-serving grace windows. Presence of ttl or expires is what makes a result cacheable; Builder#noStore overrides any freshness key.

The key strings are the single source of truth shared with the C++ extension, which reads them by string off each batch’s custom_metadata. Render them with #toMetadata() and hand the map to OutputCollector.emit(root, metadata):

`BatchUtil.emit(schema, rows, out, CacheControl.ttl(300).toMetadata(), filler);`

Booleans render as "1" and are omitted when false; unset optional fields are omitted entirely. scope is always emitted. Mirrors vgi-python’s vgi/cache_control.py.

Members

String TTL_KEY = “vgi.cache.ttl”

Freshness lifetime in whole seconds, relative to full-result receipt.

String EXPIRES_KEY = “vgi.cache.expires”

Absolute RFC 3339 UTC freshness deadline.

String NO_STORE_KEY = “vgi.cache.no_store”

Explicit “never cache”; overrides any freshness key.

String SCOPE_KEY = “vgi.cache.scope”

Reuse scope — #SCOPE_CATALOG or #SCOPE_TRANSACTION.

String ETAG_KEY = “vgi.cache.etag”

Strong validator (opaque quoted string) for conditional revalidation.

String LAST_MODIFIED_KEY = “vgi.cache.last_modified”

Weaker RFC 3339 UTC validator; fallback when no ETag.

String REVALIDATABLE_KEY = “vgi.cache.revalidatable”

The worker can check freshness cheaply without recomputing.

String STALE_WHILE_REVALIDATE_KEY = “vgi.cache.stale_while_revalidate”

Grace window (seconds) to serve stale while revalidating in the background.

String STALE_IF_ERROR_KEY = “vgi.cache.stale_if_error”

Grace window (seconds) to serve stale if a revalidation RPC fails.

String NOT_MODIFIED_KEY = “vgi.cache.not_modified”

304-equivalent, set on a 0-row batch replying to a conditional request.

String PARTITION_SCOPE_KEY = “vgi.cache.partition_scope”

Opt in to per-partition caching: the client ALSO stores the result split by partition value. Only meaningful on a SINGLE_VALUE_PARTITIONS function.

String PER_VALUE_KEY = “vgi.cache.per_value”

Opt in to per-value memoization: the client ALSO memoizes each distinct input tuple’s output. Only meaningful for an exchange-mode map (a scalar, or a blended table-in-out called via correlated LATERAL). Default OFF — see Builder#perValue(boolean) for why.

String IF_NONE_MATCH_KEY = “vgi.cache.if_none_match”

Request-side key: the client’s stored ETag, delivered on the first tick’s input custom_metadata when it asks the worker to confirm freshness.

String IF_MODIFIED_SINCE_KEY = “vgi.cache.if_modified_since”

Request-side key: the client’s stored Last-Modified validator.

String SCOPE_CATALOG = “catalog”

Reusable across transactions within the calling catalog identity (default).

String SCOPE_TRANSACTION = “transaction”

Reusable only within the transaction that produced it.

Builder builder()

A fresh builder with no freshness keys and #SCOPE_CATALOG.

CacheControl ttl(int seconds)

Shorthand for the common case: a catalog-scoped result with a freshness lifetime and nothing else.

CacheControl noStore()

Shorthand for a result the client must never store.

Map<String, String> toMetadata()

Render to the vgi.cache.* batch-metadata keys.

Map<String, String> merge(Map<String, String> metadata, CacheControl cacheControl)

Fold a cache control into an existing emit-metadata map. The rendered cache keys win on collision (last write), matching vgi-python’s _merge_cache_control.