leptos_fetch/
query_options.rs

1use std::time::Duration;
2
3pub(crate) const DEFAULT_STALE_TIME: Duration = Duration::MAX; // Never
4pub(crate) const DEFAULT_GC_TIME: Duration = Duration::from_secs(300); // 5 minutes
5
6/// Configuration to be used with [`crate::QueryClient`] and individual query scopes.
7#[derive(Debug, Clone, Copy, Default, Hash)]
8pub struct QueryOptions {
9    stale_time: Option<Duration>,
10    gc_time: Option<Duration>,
11    refetch_interval: Option<Duration>,
12}
13
14impl QueryOptions {
15    /// Create new [`QueryOptions`] with default values.
16    pub fn new() -> Self {
17        Self::default()
18    }
19
20    /// Set the duration that should pass before a query is considered stale.
21    ///
22    /// Once stale, after any new interaction with the query, a new resource using it, declarative interactions etc, the query will be refetched in the background, and update active resources.
23    ///
24    /// Default: `never`
25    #[track_caller]
26    pub fn with_stale_time(mut self, stale_time: std::time::Duration) -> Self {
27        if let Some(gc_time) = self.gc_time {
28            // If stale_time is greater than gc_time, stale_time will be set to gc_time.
29            if stale_time > gc_time {
30                self.stale_time = Some(gc_time);
31                return self;
32            }
33        }
34        self.stale_time = Some(stale_time);
35        self
36    }
37
38    /// Set the duration that should pass before an unused query is garbage collected.
39    ///
40    /// After this time, if the query isn't being used by any resources, the query will be removed from the cache, to minimise the cache's size. If the query is in active use, the gc will be scheduled to check again after the same time interval.
41    ///
42    /// To never garbage collect, set [`std::time::Duration::MAX`].
43    ///
44    /// Default: `5 minutes`
45    #[track_caller]
46    pub fn with_gc_time(mut self, gc_time: std::time::Duration) -> Self {
47        if let Some(stale_time) = self.stale_time
48            && stale_time > gc_time
49        {
50            // If stale_time is greater than gc_time, stale_time will be set to gc_time.
51            self.stale_time = Some(gc_time);
52            return self;
53        }
54        self.gc_time = Some(gc_time);
55        self
56    }
57
58    /// Set the interval after which to automatically refetch the query if there are any active resources.
59    ///
60    /// If the query is being used by any resources, it will be invalidated and refetched in the background, updating active resources according to this interval.
61    ///
62    /// Default: No refetching
63    #[track_caller]
64    pub fn with_refetch_interval(mut self, refetch_interval: std::time::Duration) -> Self {
65        self.refetch_interval = Some(refetch_interval);
66        self
67    }
68
69    /// The duration that should pass before a query is considered stale.
70    ///
71    /// Once stale, after any new interaction with the query, a new resource using it, declarative interactions etc, the query will be refetched in the background, and update active resources.
72    ///
73    /// Default: `never`
74    pub fn stale_time(&self) -> std::time::Duration {
75        self.stale_time.unwrap_or(DEFAULT_STALE_TIME)
76    }
77
78    /// The duration that should pass before an unused query is garbage collected.
79    ///
80    /// After this time, if the query isn't being used by any resources, the query will be removed from the cache, to minimise the cache's size. If the query is in active use, the gc will be scheduled to check again after the same time interval.
81    ///
82    /// Default: `5 minutes`
83    pub fn gc_time(&self) -> std::time::Duration {
84        self.gc_time.unwrap_or(DEFAULT_GC_TIME)
85    }
86
87    /// The interval (if any) after which to automatically refetch the query if there are any active resources.
88    ///
89    /// If the query is being used by any resources, it will be invalidated and refetched in the background, updating active resources according to this interval.
90    ///
91    /// Default: No refetching
92    pub fn refetch_interval(&self) -> Option<std::time::Duration> {
93        self.refetch_interval
94    }
95}
96
97pub(crate) fn safe_dt_dur_add(
98    start: chrono::DateTime<chrono::Utc>,
99    dur: std::time::Duration,
100) -> chrono::DateTime<chrono::Utc> {
101    start
102        .checked_add_signed(chrono::Duration::from_std(dur).unwrap_or(chrono::Duration::MAX))
103        .unwrap_or(chrono::DateTime::<chrono::Utc>::MAX_UTC)
104}
105
106pub(crate) fn options_combine(base: QueryOptions, scope: Option<QueryOptions>) -> QueryOptions {
107    if let Some(scope) = scope {
108        QueryOptions {
109            stale_time: scope.stale_time.or(base.stale_time),
110            gc_time: scope.gc_time.or(base.gc_time),
111            refetch_interval: scope.refetch_interval.or(base.refetch_interval),
112        }
113    } else {
114        base
115    }
116}