Skip to main content

gpui_query/core/
fetched.rs

1//! Fetcher result wrapper for server-derived cache policy ("server wins").
2//!
3//! A fetcher normally returns `Result<T, E>`. When it instead returns
4//! `Result<Fetched<T>, E>` (via the `*_with_policy` hooks in the `hook` layer),
5//! it can attach a server-derived [`CachePolicy`] that overrides the caller's
6//! per-query policy on success — so a fetcher that just read
7//! `Cache-Control: max-age=30` can push that TTL back into the resource.
8//!
9//! This type carries the data and an optional [`CachePolicy`]. Behind the
10//! `persist` feature it also carries an optional `meta` ([`serde_json::Value`])
11//! for HTTP `CacheMeta` round-trip through persistence; the ungated `core`
12//! layer (built without `persist`) stays free of `serde_json`.
13
14use crate::core::policy::CachePolicy;
15#[cfg(feature = "persist")]
16use serde_json::Value as JsonValue;
17
18/// A fetcher success carrying an optional server-derived cache policy.
19///
20/// Return this from a `*_with_policy` fetcher to let the server override the
21/// caller's [`CachePolicy`] for the resolved resource ("server wins"):
22///
23/// - [`Fetched::new`] — no policy override; the resource keeps the caller's policy.
24/// - [`Fetched::with_policy`] — override the resource's policy with the server's.
25/// - [`Fetched::with_meta`] (`persist` feature) — attach opaque metadata that
26///   flows into [`PersistedEntry::meta`](crate::client::persist::PersistedEntry)
27///   so it can be rehydrated on a cold start (e.g. an HTTP `CacheMeta` for
28///   cheap `304` refetches after relaunch).
29///
30/// `cache_policy: None` (the default) keeps the caller's per-query policy
31/// unchanged, matching the plain `Result<T, E>` fetcher behavior exactly.
32#[derive(Debug, Clone)]
33pub struct Fetched<T> {
34    /// The fetched data.
35    pub data: T,
36    /// Server-derived cache policy. `None` keeps the caller's policy.
37    pub cache_policy: Option<CachePolicy>,
38    /// Opaque metadata carried through to persistence (e.g. HTTP `CacheMeta`).
39    /// `None` unless set via [`Fetched::with_meta`]. Only present under the
40    /// `persist` feature so the ungated `core` layer stays `serde_json`-free.
41    #[cfg(feature = "persist")]
42    pub meta: Option<JsonValue>,
43}
44
45impl<T> Fetched<T> {
46    /// Wrap fetched data with **no** policy override (keep the caller's policy).
47    ///
48    /// Equivalent to returning the bare `T` from a plain `Result<T, E>` fetcher.
49    pub fn new(data: T) -> Self {
50        Self {
51            data,
52            cache_policy: None,
53            #[cfg(feature = "persist")]
54            meta: None,
55        }
56    }
57
58    /// Wrap fetched data and override the resource's cache policy with the
59    /// server's.
60    pub fn with_policy(data: T, policy: CachePolicy) -> Self {
61        Self {
62            data,
63            cache_policy: Some(policy),
64            #[cfg(feature = "persist")]
65            meta: None,
66        }
67    }
68
69    /// Attach opaque metadata (e.g. a serialized HTTP `CacheMeta`) to this
70    /// fetched value. Requires the `persist` feature; the metadata flows into
71    /// [`PersistedEntry::meta`](crate::client::persist::PersistedEntry) when the
72    /// resource is persisted, enabling cold-start revalidation.
73    #[cfg(feature = "persist")]
74    pub fn with_meta(mut self, meta: JsonValue) -> Self {
75        self.meta = Some(meta);
76        self
77    }
78}