1use std::any::TypeId;
9
10use gpui::{App, Entity};
11
12use crate::client::infinite_bucket::InfiniteQueryBucket;
13use crate::client::mutation_bucket::MutationBucket;
14use crate::core::{
15 CachePolicy, InfiniteQueryResource, MutationResource, QueryKey, QueryKeyFilter, RequestPolicy,
16};
17
18use super::QueryClient;
19
20impl QueryClient {
21 pub fn infinite_resource<T: Clone + Send + Sync + 'static, E: Clone + Send + Sync + 'static>(
25 &mut self,
26 key: impl Into<QueryKey>,
27 cx: &mut App,
28 ) -> Entity<InfiniteQueryResource<T, E>> {
29 self.infinite_resource_with_policies::<T, E>(
30 key,
31 self.default_cache_policy,
32 self.default_request_policy,
33 cx,
34 )
35 }
36
37 pub fn infinite_resource_with_policies<
41 T: Clone + Send + Sync + 'static,
42 E: Clone + Send + Sync + 'static,
43 >(
44 &mut self,
45 key: impl Into<QueryKey>,
46 cache_policy: CachePolicy,
47 request_policy: RequestPolicy,
48 cx: &mut App,
49 ) -> Entity<InfiniteQueryResource<T, E>> {
50 let type_id = TypeId::of::<(T, E)>();
51 let bucket = self
52 .infinite_buckets
53 .entry(type_id)
54 .or_insert_with(|| Box::new(InfiniteQueryBucket::<T, E>::new()));
55
56 let typed = Self::infinite_bucket_or_recreate::<T, E>(bucket);
59 let entity = typed.get_or_create(key.into(), cache_policy, request_policy, cx);
60 self.maybe_opportunistic_gc(cx);
62 entity
63 }
64
65 pub fn infinite_query<T: Clone + Send + Sync + 'static, E: Clone + Send + Sync + 'static>(
67 &self,
68 key: &QueryKey,
69 ) -> Option<Entity<InfiniteQueryResource<T, E>>> {
70 let type_id = TypeId::of::<(T, E)>();
71 self.infinite_buckets
72 .get(&type_id)
73 .and_then(|b| b.as_any().downcast_ref::<InfiniteQueryBucket<T, E>>())
74 .and_then(|b| b.get(key))
75 }
76
77 pub fn next_request_id_for_infinite_key<
86 T: Clone + Send + Sync + 'static,
87 E: Clone + Send + Sync + 'static,
88 >(
89 &mut self,
90 key: &QueryKey,
91 ) -> Option<crate::core::RequestId> {
92 let type_id = TypeId::of::<(T, E)>();
93 let bucket = self.infinite_buckets.get_mut(&type_id)?;
94 let typed = Self::infinite_bucket_or_recreate::<T, E>(bucket);
97 typed.sequencer_mut(key).map(|seq| seq.next_request())
98 }
99
100 pub fn all_infinite_queries<
102 T: Clone + Send + Sync + 'static,
103 E: Clone + Send + Sync + 'static,
104 >(
105 &self,
106 ) -> Vec<Entity<InfiniteQueryResource<T, E>>> {
107 let type_id = TypeId::of::<(T, E)>();
108 self.infinite_buckets
109 .get(&type_id)
110 .and_then(|b| b.as_any().downcast_ref::<InfiniteQueryBucket<T, E>>())
111 .map(|b| b.all_entities())
112 .unwrap_or_default()
113 }
114
115 pub fn register_mutation<
121 V: Clone + Send + Sync + 'static,
122 T: Clone + Send + Sync + 'static,
123 E: Clone + Send + Sync + 'static,
124 >(
125 &mut self,
126 entity: &Entity<MutationResource<V, T, E>>,
127 cx: &App,
128 ) {
129 let type_id = TypeId::of::<(V, T, E)>();
130 let bucket = self
131 .mutation_buckets
132 .entry(type_id)
133 .or_insert_with(|| Box::new(MutationBucket::<V, T, E>::new()));
134
135 let now_ms = crate::client::time::current_time_ms();
139 let typed = Self::mutation_bucket_or_recreate::<V, T, E>(bucket);
142 typed.insert(entity, now_ms, cx);
143 self.maybe_opportunistic_gc(cx);
146 }
147
148 pub fn all_mutations<
150 V: Clone + Send + Sync + 'static,
151 T: Clone + Send + Sync + 'static,
152 E: Clone + Send + Sync + 'static,
153 >(
154 &self,
155 ) -> Vec<Entity<MutationResource<V, T, E>>> {
156 let type_id = TypeId::of::<(V, T, E)>();
157 self.mutation_buckets
158 .get(&type_id)
159 .and_then(|b| b.as_any().downcast_ref::<MutationBucket<V, T, E>>())
160 .map(|b| b.all_entities())
161 .unwrap_or_default()
162 }
163
164 fn for_each_query_bucket_mut<F>(&mut self, mut f: F)
173 where
174 F: FnMut(EitherBucket<'_>),
175 {
176 for bucket in self.buckets.values_mut() {
177 f(EitherBucket::Query(bucket.as_mut()));
178 }
179 for bucket in self.infinite_buckets.values_mut() {
180 f(EitherBucket::Infinite(bucket.as_mut()));
181 }
182 }
183
184 pub fn invalidate_queries(&mut self, filter: &QueryKeyFilter, cx: &mut App) {
188 self.for_each_query_bucket_mut(|b| match b {
189 EitherBucket::Query(b) => b.invalidate_matching(filter, cx),
190 EitherBucket::Infinite(b) => b.invalidate_matching(filter, cx),
191 });
192 }
193
194 pub fn reset_queries(&mut self, filter: &QueryKeyFilter, cx: &mut App) {
196 self.for_each_query_bucket_mut(|b| match b {
197 EitherBucket::Query(b) => b.reset_matching(filter, cx),
198 EitherBucket::Infinite(b) => b.reset_matching(filter, cx),
199 });
200 }
201
202 pub fn remove_queries(&mut self, filter: &QueryKeyFilter) {
204 self.for_each_query_bucket_mut(|b| match b {
205 EitherBucket::Query(b) => b.remove_matching(filter),
206 EitherBucket::Infinite(b) => b.remove_matching(filter),
207 });
208 }
209
210 pub fn cancel_queries(&mut self, filter: &QueryKeyFilter, cx: &mut App) {
221 self.for_each_query_bucket_mut(|b| match b {
222 EitherBucket::Query(b) => b.cancel_matching(filter, cx),
223 EitherBucket::Infinite(b) => b.cancel_matching(filter, cx),
224 });
225 }
226
227 fn infinite_bucket_or_recreate<
237 T: Clone + Send + Sync + 'static,
238 E: Clone + Send + Sync + 'static,
239 >(
240 bucket: &mut Box<dyn super::erased::ErasedInfiniteBucket>,
241 ) -> &mut InfiniteQueryBucket<T, E> {
242 if bucket
243 .as_any_mut()
244 .downcast_mut::<InfiniteQueryBucket<T, E>>()
245 .is_none()
246 {
247 eprintln!(
248 "QueryClient: type mismatch in infinite bucket downcast for {}. \
249 Replacing with a fresh bucket.",
250 std::any::type_name::<(T, E)>()
251 );
252 *bucket = Box::new(InfiniteQueryBucket::<T, E>::new());
253 }
254 bucket
255 .as_any_mut()
256 .downcast_mut::<InfiniteQueryBucket<T, E>>()
257 .expect("InfiniteQueryBucket downcast succeeds after infinite_bucket_or_recreate")
258 }
259
260 fn mutation_bucket_or_recreate<
261 V: Clone + Send + Sync + 'static,
262 T: Clone + Send + Sync + 'static,
263 E: Clone + Send + Sync + 'static,
264 >(
265 bucket: &mut Box<dyn super::erased::ErasedMutationBucket>,
266 ) -> &mut MutationBucket<V, T, E> {
267 if bucket
268 .as_any_mut()
269 .downcast_mut::<MutationBucket<V, T, E>>()
270 .is_none()
271 {
272 eprintln!(
273 "QueryClient: type mismatch in mutation bucket downcast for {}. \
274 Replacing with a fresh bucket.",
275 std::any::type_name::<(V, T, E)>()
276 );
277 *bucket = Box::new(MutationBucket::<V, T, E>::new());
278 }
279 bucket
280 .as_any_mut()
281 .downcast_mut::<MutationBucket<V, T, E>>()
282 .expect("MutationBucket downcast succeeds after mutation_bucket_or_recreate")
283 }
284}
285
286enum EitherBucket<'a> {
288 Query(&'a mut dyn crate::client::erased::ErasedBucket),
289 Infinite(&'a mut dyn crate::client::erased::ErasedInfiniteBucket),
290}