Skip to main content

gpui_query/core/
mod.rs

1//! Layer 0: Transport-agnostic query lifecycle primitives.
2//!
3//! `QueryResource` owns the cache/request state for one resource. Callers start
4//! work with `begin_request`, then complete it with the returned `RequestId`.
5//! Completion methods reject stale request ids, so cancelled or replaced async
6//! work cannot overwrite newer state.
7//!
8//! # Request lifecycle
9//!
10//! The typical lifecycle for a single query fetch is:
11//!
12//! 1. **Begin**: Call [`QueryResource::begin_request`] with a [`RequestSequencer`].
13//!    This returns a [`QueryBeginResult`] indicating whether a fetch is needed,
14//!    the cache was hit, or the request was ignored.
15//!
16//! 2. **Fetch**: If the result is [`Started`](QueryBeginResult::Started) or
17//!    [`StaleCacheHit`](QueryBeginResult::StaleCacheHit), start an async fetch
18//!    using the returned [`RequestId`].
19//!
20//! 3. **Accept**: When the fetch completes, call
21//!    [`QueryResource::accept_current_request`] with the `RequestId`. If the
22//!    request is still active (not replaced or cancelled), this returns a
23//!    [`RequestGuard`] — a single-use capability token.
24//!
25//! 4. **Complete**: Pass the [`RequestGuard`] (by value) to
26//!    [`QueryResource::complete_success`] or [`QueryResource::complete_failure`].
27//!    The guard is consumed, preventing accidental double-completion.
28//!
29//! Alternatively, use the convenience methods [`QueryResource::complete_current_success`]
30//! or [`QueryResource::complete_current_failure`] which combine steps 3 and 4.
31//!
32//! This module depends only on `serde` — zero framework coupling.
33
34mod error;
35mod fetched;
36mod infinite_query;
37mod key;
38mod key_filter;
39mod mutation;
40mod network_mode;
41mod policy;
42mod refetch;
43mod request;
44mod resource;
45mod retry;
46mod select;
47mod signal;
48mod status;
49
50pub use error::{QueryError, QueryErrorKind};
51pub use fetched::Fetched;
52pub use infinite_query::{FetchDirection, InfiniteQueryResource};
53pub use key::QueryKey;
54pub use key_filter::QueryKeyFilter;
55pub use mutation::{MutationResource, MutationStatus};
56pub use network_mode::NetworkMode;
57pub use policy::{CachePolicy, QueryBeginResult, QueryFetchMode, RequestPolicy};
58pub use refetch::RefetchTrigger;
59pub use request::{QueryTimestamp, RequestGuard, RequestId, RequestSequencer};
60pub use resource::QueryResource;
61pub use retry::RetryPolicy;
62pub use select::{MappedQueryResource, SelectTransform};
63pub use signal::QuerySignal;
64pub use status::QueryStatus;
65
66// ── Task storage helper (client feature) ────────────────────────────────
67//
68// `gpui::Task<T>` is `Debug` but not `Clone`, `PartialEq`, or `Eq`. Several
69// resource structs derive `Clone`/`PartialEq`/`Eq`, so storing a raw
70// `Option<Task<()>>` would break those derives when the `client` feature is
71// enabled. `CurrentTask` is a thin newtype that implements `Clone` (producing
72// an empty handle — the original task keeps running), `PartialEq`/`Eq`
73// (treating all instances as equal — task identity does not affect resource
74// equality), and `Default` (no task). Dropping the inner `Task` cancels it
75// immediately (gpui semantics), so `set` and `abort` simply replace the
76// inner value, dropping the previous task.
77#[cfg(feature = "client")]
78mod current_task {
79    use gpui::Task;
80
81    #[derive(Debug, Default)]
82    pub(crate) struct CurrentTask(Option<Task<()>>);
83
84    impl Clone for CurrentTask {
85        fn clone(&self) -> Self {
86            Self(None)
87        }
88    }
89
90    impl PartialEq for CurrentTask {
91        fn eq(&self, _other: &Self) -> bool {
92            true
93        }
94    }
95
96    impl Eq for CurrentTask {}
97
98    impl CurrentTask {
99        pub(crate) fn set(&mut self, task: Task<()>) {
100            self.0 = Some(task);
101        }
102    }
103}