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}