1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
use TokenStream;
/// Define a memoized function using a cache store that implements `cached::Cached` (and
/// `cached::CachedAsync` for async functions)
///
/// # Attributes
/// - `name`: (optional, string) specify the name for the generated cache, defaults to the function name uppercase.
/// - `size`: (optional, usize) specify an LRU max size, implies the cache type is a `LruCache` or `LruTtlCache`.
/// - `ttl`: (optional, u64) specify a cache TTL in seconds, implies the cache type is a `TtlCache` or `LruTtlCache`.
/// - `refresh`: (optional, bool) specify whether to refresh the TTL on cache hits.
/// - `sync_writes`: (optional, bool or string) specify whether to synchronize the execution and writing of uncached values.
/// When not specified or set to `false`, uncached calls execute without write synchronization. When set to `true`
/// or `"default"`, all keys synchronize by locking the whole cache during uncached execution. When set to
/// `"by_key"`, a per-key lock synchronizes uncached execution of duplicate keys only.
/// - `sync_writes_buckets`: (optional, usize) number of per-key lock buckets used by
/// `sync_writes = "by_key"`; defaults to 64. Each bucket is one `Arc<RwLock<()>>`. Keys
/// hash into a bucket, so two different keys may share a bucket and serialize unnecessarily
/// (false sharing). Increase this if you observe contention under high concurrency — a value
/// around 2–4× your expected peak concurrency eliminates most false sharing. Must be > 0.
/// - `sync_lock`: (optional, string) choose the generated cache lock. Defaults to `"rwlock"`. Use `"mutex"`
/// to force a mutex. `unsync_reads = true` requires an RwLock.
/// - `unsync_reads`: (optional, bool) use `CachedRead::cache_get_read` under a shared read lock for the initial
/// cache lookup, while keeping writes synchronized. This only works for stores that implement `CachedRead`;
/// recency-updating or refresh-on-hit stores intentionally do not. For non-mutating diagnostic lookups,
/// use the separate `CachedPeek` trait directly on stores.
/// - `ty`: (optional, string type) The cache store type to use. Defaults to `UnboundCache`. When `unbound` is
/// specified, defaults to `UnboundCache`. When `size` is specified, defaults to `LruCache`.
/// When `ttl` is specified, defaults to `TtlCache`.
/// When `size` and `ttl` are specified, defaults to `LruTtlCache`. When `ty` is
/// specified, `create` must also be specified.
/// - `create`: (optional, string expr) specify an expression used to create a new cache store, e.g. `create = r##"{ CacheType::new() }"##`.
/// - `key`: (optional, string type) specify what type to use for the cache key, e.g. `key = "u32"`.
/// When `key` is specified, `convert` must also be specified.
/// - `convert`: (optional, string expr) specify an expression used to convert function arguments to a cache
/// key, e.g. `convert = r##"{ format!("{}:{}", arg1, arg2) }"##`. When `convert` is specified,
/// `key` or `ty` must also be set.
/// - `result`: (optional, bool) If your function returns a `Result`, only cache `Ok` values returned by the function.
/// - `option`: (optional, bool) If your function returns an `Option`, only cache `Some` values returned by the function.
/// - `with_cached_flag`: (optional, bool) If your function returns a `cached::Return` or `Result<cached::Return, E>`,
/// the `cached::Return.was_cached` flag will be updated when a cached value is returned.
/// The wrapper type **must** be `cached::Return` — either written fully
/// qualified, or imported from `cached` (`use cached::Return;`). A proc macro
/// only sees tokens, not resolved types: an unrelated type that merely happens
/// to be named `Return<T>` passes the attribute check but then fails to
/// compile in the generated body (it calls `::cached::Return::new` /
/// `.was_cached`). Use a different name for any non-`cached` `Return` type.
/// - `result_fallback`: (optional, bool) If your function returns a `Result` and it fails, the cache will instead refresh the recently expired `Ok` value.
/// In other words, refreshes are best-effort - returning `Ok` refreshes as usual but `Err` falls back to the last `Ok`.
/// This is useful, for example, for keeping the last successful result of a network operation even during network disconnects.
/// *Note*, this option requires the cache type to implement `CloneCached`. The compatible built-in options are:
/// `ttl` (uses `TtlCache`), `size` + `ttl` (uses `LruTtlCache`), and `expires` (uses `ExpiringCache`/`ExpiringLruCache`).
/// A custom `ty` that implements `CloneCached` is also accepted.
/// - `expires`: (optional, bool) Auto-select an expiry-aware store whose entries expire based on
/// per-value logic rather than a single global TTL.
/// The return type (or its inner type when `result`/`option` is also set) must implement `Expires`.
/// Without `size`, uses `ExpiringCache` (unbounded).
/// With `size = N`, uses `ExpiringLruCache` (LRU-bounded to N entries).
/// Unlike `ttl`, expiry logic lives in each value — useful for caching OAuth tokens,
/// HTTP responses with `Cache-Control` headers, or any payload with its own expiration timestamp.
/// Compatible with `result_fallback`: on `Err`, returns the last-cached `Ok` value wrapped in `Ok(...)`,
/// even if that value's `is_expired()` returns `true`. Callers must check the value's expiry themselves
/// if they need to distinguish a fresh result from a stale fallback.
/// Mutually exclusive with `ttl`, `ty`, `create`, `with_cached_flag`, `unsync_reads`, `refresh`, and `unbound`.
///
/// ## Note
/// The `ty`, `create`, `key`, and `convert` attributes must be in a `String`
/// This is because darling, which is used for parsing the attributes, does not support directly parsing
/// attributes into `Type`s or `Block`s.
/// Define a memoized function using a cache store that implements `cached::Cached` (and
/// `cached::CachedAsync` for async functions). Function arguments are not used to identify
/// a cached value, only one value is cached unless a `ttl` expiry is specified.
///
/// # Attributes
/// - `name`: (optional, string) specify the name for the generated cache, defaults to the function name uppercase.
/// - `ttl`: (optional, u64) specify an expiry in seconds, after which the single cached value is
/// recomputed on the next call. `#[once]` always stores one value in an `Option` (timestamped
/// when `ttl` is set) — it is not a `TtlCache`/`LruTtlCache`.
/// - `sync_writes`: (optional, bool or string) specify whether to synchronize the execution of writing of uncached values.
/// When set to `true` or `"default"`, uncached execution is synchronized with the whole cache.
/// When omitted or set to `false`, uncached calls are not synchronized. `sync_writes = "by_key"`
/// is not supported by `#[once]` because a `#[once]` cache stores a single value for all arguments.
/// - `result`: (optional, bool) If your function returns a `Result`, only cache `Ok` values returned by the function.
/// - `option`: (optional, bool) If your function returns an `Option`, only cache `Some` values returned by the function.
/// - `with_cached_flag`: (optional, bool) If your function returns a `cached::Return` or `Result<cached::Return, E>`,
/// the `cached::Return.was_cached` flag will be updated when a cached value is returned.
/// The wrapper type **must** be `cached::Return` — either written fully
/// qualified, or imported from `cached` (`use cached::Return;`). A proc macro
/// only sees tokens, not resolved types: an unrelated type that merely happens
/// to be named `Return<T>` passes the attribute check but then fails to
/// compile in the generated body (it calls `::cached::Return::new` /
/// `.was_cached`). Use a different name for any non-`cached` `Return` type.
/// - `expires`: (optional, bool) Delegate expiry to the cached value instead of a fixed TTL.
/// The return type (or its inner type when `result`/`option` is also set) must implement `Expires`.
/// When a lookup finds the cached value reports `is_expired() == true`, the cached value is
/// skipped and the function re-executes; on success the new value replaces the old one.
/// If the function returns `Err`/`None`, the expired entry is left in place and the error/none
/// is returned to the caller — subsequent calls will re-execute the function until it succeeds.
/// Mutually exclusive with `ttl` and `with_cached_flag`.
/// Define a memoized function using a cache store that implements `cached::ConcurrentCached` (and
/// `cached::ConcurrentCachedAsync` for async functions)
///
/// # Attributes
/// - `map_error`: (string, expr closure) specify a closure used to map any IO-store errors into
/// the error type returned by your function.
/// - `name`: (optional, string) specify the name for the generated cache, defaults to the function name uppercase.
/// - `redis`: (optional, bool) default to a `RedisCache` or `AsyncRedisCache`
/// - `disk`: (optional, bool) use a `DiskCache`, this must be set to true even if `type` and `create` are specified.
/// On an `async fn`, `sled`'s blocking I/O is run on `tokio`'s blocking pool via
/// `spawn_blocking` (so it does not stall the async runtime); this requires a Tokio
/// runtime context and surfaces a `DiskCacheError::BackgroundTaskFailed` if that task is
/// cancelled or panics.
/// - `ttl`: (optional, u64) specify a cache TTL in seconds, applied to the backing concurrent store
/// (e.g. the Redis key expiry, or the `DiskCache` entry TTL). `#[concurrent_cached]` uses a
/// Redis/disk/custom `ConcurrentCached` store, not a `TtlCache`/`LruTtlCache`.
/// - `refresh`: (optional, bool) specify whether to refresh the TTL on cache hits.
/// - `ty`: (optional, string type) explicitly specify the cache store type to use.
/// - `cache_prefix_block`: (optional, string expr) specify an expression used to create the string used as a
/// prefix for all cache keys of this function, e.g. `cache_prefix_block = r##"{ "my_prefix" }"##`.
/// When not specified, the cache prefix will be constructed from the name of the function. This
/// could result in unexpected conflicts between concurrent_cached-functions of the same name, so it's
/// recommended that you specify a prefix you're sure will be unique.
/// - `create`: (optional, string expr) specify an expression used to create a new cache store, e.g. `create = r##"{ CacheType::new() }"##`.
/// - `key`: (optional, string type) specify what type to use for the cache key, e.g. `key = "u32"`.
/// When `key` is specified, `convert` must also be specified.
/// - `convert`: (optional, string expr) specify an expression used to convert function arguments to a cache
/// key, e.g. `convert = r##"{ format!("{}:{}", arg1, arg2) }"##`. When `convert` is specified,
/// `key` or `ty` must also be set.
/// - `with_cached_flag`: (optional, bool) If your function returns a `cached::Return` or `Result<cached::Return, E>`,
/// the `cached::Return.was_cached` flag will be updated when a cached value is returned.
/// The wrapper type **must** be `cached::Return` — either written fully
/// qualified, or imported from `cached` (`use cached::Return;`). A proc macro
/// only sees tokens, not resolved types: an unrelated type that merely happens
/// to be named `Return<T>` passes the attribute check but then fails to
/// compile in the generated body (it calls `::cached::Return::new` /
/// `.was_cached`). Use a different name for any non-`cached` `Return` type.
/// - `sync_to_disk_on_cache_change`: (optional, bool) in the case of `DiskCache` specify whether to synchronize the cache to disk each
/// time the cache changes.
/// - connection_config: (optional, string expr) specify an expression which returns a `sled::Config`
/// to give more control over the connection to the disk cache, i.e. useful for controlling the rate at which the cache syncs to disk.
/// See the docs of `cached::stores::DiskCacheBuilder::connection_config` for more info.
///
/// ## Note
/// The `ty`, `create`, `key`, and `convert` attributes must be in a `String`
/// This is because darling, which is used for parsing the attributes, does not support directly parsing
/// attributes into `Type`s or `Block`s.