Skip to content

Commit 019cfd1

Browse files
committed
release 0.55.0
1 parent 088a4b6 commit 019cfd1

File tree

9 files changed

+35
-26
lines changed

9 files changed

+35
-26
lines changed

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
## Changed
66
## Removed
77

8+
## [0.55.0]
9+
## Added
10+
- Add `sync_writes = "by_key"` support to `#[cached]
11+
## Changed
12+
- Update `redis` to 0.29.0
13+
- Update `directories` to 6.0
14+
- Update `thiserror` to 2.0
15+
- With the `sync_writes = "by_key"` addition, the argument values changed from a boolean
16+
to strings. The equivalent of `sync_writes = true` is now `sync_writes = "default"`
17+
## Removed
18+
819
## [0.54.0]
920
## Added
1021
- Add `Cached::cache_try_get_or_set_with` for parity with async trait

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cached"
3-
version = "0.54.0"
3+
version = "0.55.0"
44
authors = ["James Kominick <[email protected]>"]
55
description = "Generic cache implementations and simplified function memoization"
66
repository = "https://github.com/jaemk/cached"

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function-cache wrapped in a mutex/rwlock, or externally synchronized in the case
1414
By default, the function-cache is **not** locked for the duration of the function's execution, so initial (on an empty cache)
1515
concurrent calls of long-running functions with the same arguments will each execute fully and each overwrite
1616
the memoized value as they complete. This mirrors the behavior of Python's `functools.lru_cache`. To synchronize the execution and caching
17-
of un-cached arguments, specify `#[cached(sync_writes = "default")]` / `#[once(sync_writes = "default")]` (not supported by `#[io_cached]`.
17+
of un-cached arguments, specify `#[cached(sync_writes = "default")]` / `#[once(sync_writes = true)]` (not supported by `#[io_cached]`.
1818

1919
- See [`cached::stores` docs](https://docs.rs/cached/latest/cached/stores/index.html) cache stores available.
2020
- See [`proc_macro`](https://docs.rs/cached/latest/cached/proc_macro/index.html) for more procedural macro examples.
@@ -93,7 +93,7 @@ use cached::proc_macro::once;
9393
/// When no (or expired) cache, concurrent calls
9494
/// will synchronize (`sync_writes`) so the function
9595
/// is only executed once.
96-
#[once(time=10, option = true, sync_writes = "default")]
96+
#[once(time=10, option = true, sync_writes = true)]
9797
fn keyed(a: String) -> Option<usize> {
9898
if a == "a" {
9999
Some(a.len())

cached_proc_macro/src/lib.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ use proc_macro::TokenStream;
1313
/// - `size`: (optional, usize) specify an LRU max size, implies the cache type is a `SizedCache` or `TimedSizedCache`.
1414
/// - `time`: (optional, u64) specify a cache TTL in seconds, implies the cache type is a `TimedCache` or `TimedSizedCache`.
1515
/// - `time_refresh`: (optional, bool) specify whether to refresh the TTL on cache hits.
16-
/// - `sync_writes`: (optional, bool) specify whether to synchronize the execution of writing of uncached values.
17-
/// - `sync_writes_by_key`: (optional, bool) specify whether to synchronize the execution of writing of uncached values by key.
16+
/// - `sync_writes`: (optional, string) specify whether to synchronize the execution and writing of uncached values.
17+
/// When not specified, the `"default"` behavior will synchronize all keys, locking the whole cache during an
18+
/// uncached execution. When set to `"by_key"` a per-key lock is used to synchronize uncached execution of
19+
/// duplicate keys only.
1820
/// - `ty`: (optional, string type) The cache store type to use. Defaults to `UnboundCache`. When `unbound` is
1921
/// specified, defaults to `UnboundCache`. When `size` is specified, defaults to `SizedCache`.
2022
/// When `time` is specified, defaults to `TimedCached`.

cached_proc_macro/src/once.rs

+7-12
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,14 @@ use quote::quote;
66
use syn::spanned::Spanned;
77
use syn::{parse_macro_input, Ident, ItemFn, ReturnType};
88

9-
#[derive(Debug, Default, FromMeta)]
10-
enum SyncWriteMode {
11-
#[default]
12-
Default,
13-
}
14-
159
#[derive(FromMeta)]
1610
struct OnceMacroArgs {
1711
#[darling(default)]
1812
name: Option<String>,
1913
#[darling(default)]
2014
time: Option<u64>,
2115
#[darling(default)]
22-
sync_writes: Option<SyncWriteMode>,
16+
sync_writes: bool,
2317
#[darling(default)]
2418
result: bool,
2519
#[darling(default)]
@@ -226,22 +220,23 @@ pub fn once(args: TokenStream, input: TokenStream) -> TokenStream {
226220
}
227221
};
228222

229-
let do_set_return_block = match args.sync_writes {
230-
Some(SyncWriteMode::Default) => quote! {
223+
let do_set_return_block = if args.sync_writes {
224+
quote! {
231225
#r_lock_return_cache_block
232226
#w_lock
233227
if let Some(result) = &*cached {
234228
#return_cache_block
235229
}
236230
#function_call
237231
#set_cache_and_return
238-
},
239-
None => quote! {
232+
}
233+
} else {
234+
quote! {
240235
#r_lock_return_cache_block
241236
#function_call
242237
#w_lock
243238
#set_cache_and_return
244-
},
239+
}
245240
};
246241

247242
let signature_no_muts = get_mut_signature(signature);

examples/async_std.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ async fn only_cached_once_per_second(s: String) -> Vec<String> {
8686
/// _one_ call will be "executed" and all others will be synchronized
8787
/// to return the cached result of the one call instead of all
8888
/// concurrently un-cached tasks executing and writing concurrently.
89-
#[once(time = 2, sync_writes = "default")]
89+
#[once(time = 2, sync_writes = true)]
9090
async fn only_cached_once_per_second_sync_writes(s: String) -> Vec<String> {
9191
vec![s]
9292
}

src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ function-cache wrapped in a mutex/rwlock, or externally synchronized in the case
1313
By default, the function-cache is **not** locked for the duration of the function's execution, so initial (on an empty cache)
1414
concurrent calls of long-running functions with the same arguments will each execute fully and each overwrite
1515
the memoized value as they complete. This mirrors the behavior of Python's `functools.lru_cache`. To synchronize the execution and caching
16-
of un-cached arguments, specify `#[cached(sync_writes = "default")]` / `#[once(sync_writes = "default")]` (not supported by `#[io_cached]`.
16+
of un-cached arguments, specify `#[cached(sync_writes = "default")]` / `#[once(sync_writes = true)]` (not supported by `#[io_cached]`.
1717
1818
- See [`cached::stores` docs](https://docs.rs/cached/latest/cached/stores/index.html) cache stores available.
1919
- See [`proc_macro`](https://docs.rs/cached/latest/cached/proc_macro/index.html) for more procedural macro examples.
@@ -94,7 +94,7 @@ use cached::proc_macro::once;
9494
/// When no (or expired) cache, concurrent calls
9595
/// will synchronize (`sync_writes`) so the function
9696
/// is only executed once.
97-
#[once(time=10, option = true, sync_writes = "default")]
97+
#[once(time=10, option = true, sync_writes = true)]
9898
fn keyed(a: String) -> Option<usize> {
9999
if a == "a" {
100100
Some(a.len())

src/proc_macro.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ use cached::proc_macro::once;
233233
/// When no (or expired) cache, concurrent calls
234234
/// will synchronize (`sync_writes`) so the function
235235
/// is only executed once.
236-
#[once(time=10, option = true, sync_writes = "default")]
236+
#[once(time=10, option = true, sync_writes = true)]
237237
fn keyed(a: String) -> Option<usize> {
238238
if a == "a" {
239239
Some(a.len())

tests/cached.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ cached_control! {
328328
Key = { input.to_owned() };
329329
PostGet(cached_val) = return Ok(cached_val.clone());
330330
PostExec(body_result) = {
331+
#[allow(clippy::question_mark)]
331332
match body_result {
332333
Ok(v) => v,
333334
Err(e) => return Err(e),
@@ -848,7 +849,7 @@ async fn test_only_cached_option_once_per_second_a() {
848849
/// to return the cached result of the one call instead of all
849850
/// concurrently un-cached tasks executing and writing concurrently.
850851
#[cfg(feature = "async")]
851-
#[once(time = 2, sync_writes = "default")]
852+
#[once(time = 2, sync_writes)]
852853
async fn only_cached_once_per_second_sync_writes(s: String) -> Vec<String> {
853854
vec![s]
854855
}
@@ -910,9 +911,9 @@ fn test_cached_sync_writes_by_key() {
910911
let b = std::thread::spawn(|| cached_sync_writes_by_key("b".to_string()));
911912
let c = std::thread::spawn(|| cached_sync_writes_by_key("c".to_string()));
912913
let start = Instant::now();
913-
let a = a.join().unwrap();
914-
let b = b.join().unwrap();
915-
let c = c.join().unwrap();
914+
let _ = a.join().unwrap();
915+
let _ = b.join().unwrap();
916+
let _ = c.join().unwrap();
916917
assert!(start.elapsed() < Duration::from_secs(2));
917918
}
918919

@@ -942,7 +943,7 @@ async fn test_cached_sync_writes_by_key_a() {
942943
}
943944

944945
#[cfg(feature = "async")]
945-
#[once(sync_writes = "default")]
946+
#[once(sync_writes = true)]
946947
async fn once_sync_writes_a(s: &tokio::sync::Mutex<String>) -> String {
947948
let mut guard = s.lock().await;
948949
let results: String = (*guard).clone().to_string();

0 commit comments

Comments
 (0)