query

package
v4.0.0 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package query is GoWebComponents' stable query/data layer: a keyed, concurrency-safe cache with request de-duplication, stale-while-revalidate (SWR) refresh, invalidate-by-key, and one-call optimistic mutations with automatic rollback.

It is the Go-native answer to TanStack Query / SWR, with two deliberate differences:

  • It is EXPLICIT, not magical. You pass the cache key and the fetcher to every call; nothing is auto-tracked behind your back. This matches the framework's core design direction (no hidden reactive graph) and keeps every call site readable.
  • It is PURE Go. The fetcher is an ordinary func() (T, error), so the entire layer compiles and is fully unit-testable both natively and as wasm — no JS, no network stubs, no fake timers needed (the clock is injectable for tests).

Typical use:

c := query.New(query.WithStaleTime(30 * time.Second))
res := query.Fetch(c, "user/42", func() (User, error) { return api.GetUser(42) })
// concurrent Fetch("user/42", …) calls coalesce into ONE api.GetUser call.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MutateAsync

func MutateAsync[T any](parseC *Cache, parseKey string, parseOptimistic T, parseFn func() (T, error), parseOnSettled func(Result[T]))

MutateAsync applies the optimistic value to key immediately (so a Snapshot taken right after already reflects it) and runs fn in the background, committing fn's result on success or rolling back to the exact prior state on error, then invoking onSettled (may be nil) with the outcome. This is the fire-and-forget optimistic action: the UI updates now and the server reconciles later — pair fn with serverfn.Call to make a one-call optimistic server action.

Types

type Cache

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

Cache is a concurrency-safe keyed query cache. Create one per logical data scope (commonly one app-wide cache) and share it; all methods are safe for concurrent use.

func New

func New(parseOpts ...Option) *Cache

New creates an empty cache with the given options.

func (*Cache) Inspect

func (parseC *Cache) Inspect() []EntryInfo

Inspect returns a sorted, type-erased view of every cache entry — the data a devtools cache panel renders (which keys are cached, fresh/stale, currently fetching).

func (*Cache) Invalidate

func (parseC *Cache) Invalidate(parseKey string)

Invalidate marks key stale so the next Fetch/SWR refetches it. In-flight fetches are left untouched.

func (*Cache) InvalidateAll

func (parseC *Cache) InvalidateAll()

InvalidateAll marks every cached key stale so the next read of each refetches. This is the global cache-bust used on sign-in/sign-out or a window-focus/reconnect revalidation.

func (*Cache) InvalidatePrefix

func (parseC *Cache) InvalidatePrefix(parsePrefix string)

InvalidatePrefix marks every key sharing prefix stale — the by-scope invalidation that makes keys like "user/42/posts" cheap to refresh as a group.

func (*Cache) Keys

func (parseC *Cache) Keys() []string

Keys returns a sorted snapshot of the cached keys — for devtools, introspection, and deciding which queries a focus/reconnect handler should revalidate.

func (*Cache) Peek

func (parseC *Cache) Peek(parseKey string) (any, bool)

Peek returns the cached value for key without triggering a fetch.

func (*Cache) Set

func (parseC *Cache) Set(parseKey string, parseData any)

Set seeds or overwrites the cached value for key (e.g. priming from SSR data or a mutation response), marking it freshly updated.

type EntryInfo

type EntryInfo struct {
	Key       string
	HasData   bool
	Stale     bool
	Fetching  bool
	UpdatedAt time.Time
}

EntryInfo is a non-generic, type-erased view of one cache entry for observability — the devtools surface that does not know each key's concrete type.

type Option

type Option func(*Cache)

Option configures a Cache at construction.

func WithClock

func WithClock(parseNow func() time.Time) Option

WithClock injects the clock used for freshness decisions (defaults to time.Now). Supply a deterministic clock to make staleness testable without sleeping, or a server-synchronized clock so cache TTLs agree with an authoritative time source.

func WithStaleTime

func WithStaleTime(parseD time.Duration) Option

WithStaleTime sets how long fetched data is considered fresh. Within this window Fetch returns cached data without calling the fetcher and SWR skips revalidation. The default is 0: every read revalidates (concurrent reads still coalesce).

type Result

type Result[T any] struct {
	// Data is the cached value (zero if none has been fetched successfully).
	Data T
	// Err is the most recent error for this key, or nil.
	Err error
	// Status is the lifecycle state at snapshot time.
	Status Status
	// UpdatedAt is when Data was last written, zero if never.
	UpdatedAt time.Time
	// Stale is true when Data is older than the cache's stale time (SWR will refresh).
	Stale bool
	// Fetching is true when a background or foreground fetch is in flight.
	Fetching bool
}

Result is an immutable snapshot of a cached query at one moment.

func Fetch

func Fetch[T any](parseC *Cache, parseKey string, parseFn func() (T, error)) Result[T]

Fetch returns the cached value for key when fresh; otherwise it invokes fn — coalescing all concurrent Fetch calls for the same key into a single fn invocation — caches the result, and returns it. This is the blocking, read-through path.

func Mutate

func Mutate[T any](parseC *Cache, parseKey string, parseOptimistic T, parseFn func() (T, error)) Result[T]

Mutate applies an optimistic value to key immediately, runs fn, and on success commits fn's returned value to the cache — or, on error, rolls the cache back to exactly the pre-mutation state and reports the error in the returned Result. This is the optimistic-update-with-rollback path that JS query libs make you wire by hand.

func SWR

func SWR[T any](parseC *Cache, parseKey string, parseFn func() (T, error), parseOnUpdate func(Result[T])) Result[T]

SWR returns the cached value immediately (possibly empty or stale) and, when the data is missing or stale and no fetch is already running, starts a background refresh. onUpdate (may be nil) is called once with the fresh result when that refresh completes, which is where a component re-renders. Concurrent SWR/Fetch calls share one refresh.

func Snapshot

func Snapshot[T any](parseC *Cache, parseKey string) Result[T]

Snapshot returns the current typed result for key WITHOUT triggering a fetch. It is the pure read a render uses to project current cache state into the view; pair it with SWR (or the ui.UseQuery hook) to drive the actual revalidation.

type Status

type Status int

Status is the lifecycle state of a cached query result.

const (
	// StatusIdle means the key has never been fetched and holds no data.
	StatusIdle Status = iota
	// StatusLoading means a fetch is in flight and no data is cached yet.
	StatusLoading
	// StatusSuccess means data is cached (it may be stale and revalidating).
	StatusSuccess
	// StatusError means the last fetch failed and no prior data is cached.
	StatusError
)

func (Status) String

func (parseS Status) String() string

String renders the status for logs and diagnostics.

Directories

Path Synopsis
Package devtools renders the query cache's observability panel as a GoWebComponents component (D2).
Package devtools renders the query cache's observability panel as a GoWebComponents component (D2).

Jump to

Keyboard shortcuts

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