gquery

Types

Represents the full lifecycle of a remotely fetched value.

  • NotAsked — no fetch has been attempted yet.
  • Loading — a fetch is in progress. Carries optional stale data so the UI can display the previous value while revalidating.
  • Loaded — the last fetch succeeded. at is the Unix timestamp in milliseconds at which the data was recorded.
  • Failed — the last fetch failed with an error.
pub type Entry(data, err) {
  NotAsked
  Loading(stale: option.Option(data))
  Loaded(data: data, at: Int)
  Failed(err: err)
}

Constructors

  • NotAsked
  • Loading(stale: option.Option(data))
  • Loaded(data: data, at: Int)
  • Failed(err: err)

Values

pub const always_stale: Int

Pass to stale_ms to always consider an entry stale. The fetch will fire on every call to query.

pub fn get_data(entry: Entry(a, e)) -> option.Option(a)

Returns the most recent data held by the entry, if any.

Returns Some(data) for Loaded and Loading(Some(data)) (stale-while- revalidate). Returns None for NotAsked, Failed, and Loading(None).

case gleam_query.get_data(entry) {
  Some(contacts) -> render_list(contacts)
  None -> render_empty()
}
pub fn invalidate(entry: Entry(a, e)) -> Entry(a, e)

Marks a loaded entry as stale, transitioning it to Loading while preserving the existing data for display during revalidation.

  • Loaded(data, _)Loading(Some(data))
  • Loading(_) → unchanged (fetch already in progress)
  • NotAsked → unchanged (nothing to preserve)
  • Failed(_)NotAsked (retry from a clean state)

Call this after a successful mutation to trigger a background refetch on the next access.

let contacts = dict.map_values(cache.contacts, fn(_, e) {
  gleam_query.invalidate(e)
})
pub fn is_stale(
  entry: Entry(a, e),
  stale_ms: Int,
  now_ms: Int,
) -> Bool

Returns True when the entry needs a fresh fetch.

  • NotAsked and Failed are always considered stale.
  • Loading is never stale (a fetch is already in flight).
  • Loaded is stale when now_ms - at > stale_ms.
gleam_query.is_stale(entry, stale_ms: 30_000, now_ms: now())
pub const never_stale: Int

Pass to stale_ms to never consider a loaded entry stale. The fetch fires only once; the data is kept until manually invalidated.

pub fn record(
  result: Result(data, err),
  now_ms: Int,
) -> Entry(data, err)

Creates an Entry from a fetch result and a current timestamp.

  • Ok(data)Loaded(data, at: now_ms)
  • Error(err)Failed(err)

Prefer gleam_query/lustre.record in Lustre apps — it captures the current timestamp automatically.

let entry = gleam_query.record(result, now_ms: current_time_ms())
Search Document