-
-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
optionally_try_get_with in moka::future::Cache #254
Comments
Hi. Sorry for a late reply. I reviewed the current code of For now, you could workaround by using use thiserror::Error;
/// An error type that can be converted from `Option<Result<V, std::io::Error>>`.
#[derive(Error, Debug)]
pub enum MyError {
/// No such key. Used when the key does not exist (`None`).
#[error("no such key")]
NoSuchKey,
/// I/O error. Used when the key exists but the value cannot be retrieved
/// (`Some(Err(_))`).
#[error(transparent)]
Io(#[from] std::io::Error),
} and then, define a function to convert fn convert(v: Option<Result<V, std::io::Error>>) -> Result<V, MyError> {
match v {
Some(Ok(v)) => Ok(v),
Some(Err(e)) => Err(MyError::Io(e)),
None => Err(MyError::NoSuchKey),
}
} Here is a working example: // Cargo.toml
//
// [dependencies]
// moka = { version = "0.10.2", features = ["future"] }
// thiserror = "1.0.40"
// tokio = { version = "1.27.0", features = ["rt-multi-thread", "macros"] }
use moka::future::Cache;
use thiserror::Error;
type K = i32;
type V = char;
/// Try to retrieve a value from somewhere for the given key, and returns one of
/// the following values:
///
/// - `None` if the key does not exist.
/// - `Some(Ok(value))` if the key exists and the value can be retrieved.
/// - `Some(Err(error))` if the key exists but the value cannot be retrieved.
async fn retrieve_value(key: &K) -> Option<Result<V, std::io::Error>> {
match key {
// For a demonstration purpose, return a hard-coded value for the given key.
0 => Some(Ok('0')),
1 => Some(Err(std::io::Error::new(
std::io::ErrorKind::Other,
"some io error",
))),
2 => None,
_ => unreachable!(),
}
}
/// An error type that can be converted from `Option<Result<V, std::io::Error>>`.
#[derive(Error, Debug)]
pub enum MyError {
/// No such key. Used when the key does not exist (`None`).
#[error("no such key")]
NoSuchKey,
/// I/O error. Used when the key exists but the value cannot be retrieved
/// (`Some(Err(_))`).
#[error(transparent)]
Io(#[from] std::io::Error),
}
/// Converts a value that returned from `retrieve_value()` into a value that can
/// be passed to `try_get_with()`.
fn convert(v: Option<Result<V, std::io::Error>>) -> Result<V, MyError> {
match v {
Some(Ok(v)) => Ok(v),
Some(Err(e)) => Err(MyError::Io(e)),
None => Err(MyError::NoSuchKey),
}
}
#[tokio::main]
async fn main() {
let cache = Cache::builder().build();
// A case that retrieve_value() returns Some(Ok('0')).
let key0 = 0;
let result = cache
.try_get_with(key0, async { convert(retrieve_value(&key0).await) })
.await;
// Expects `Ok('0')`
assert!(matches!(result, Ok('0')));
assert!(matches!(cache.get(&key0), Some('0')));
// A case that retrieve_value() returns Some(Err(std::io::Error)).
let key1 = 1;
let result = cache
.try_get_with(key1, async { convert(retrieve_value(&key1).await) })
.await;
// Expects `Err<Arc<MyError>>` when `MyError` is `Io(std::io::Error)`.
assert!(matches!(result, Err(e) if matches!(*e, MyError::Io(_))));
assert!(!cache.contains_key(&key1));
// A case that retrieve_value() returns None.
let key2 = 2;
let result = cache
.try_get_with(key2, async { convert(retrieve_value(&key2).await) })
.await;
// Expects `Err<Arc<MyError>>` when `MyError` is `NoSuchKey`.
assert!(matches!(result, Err(e) if matches!(*e, MyError::NoSuchKey)));
assert!(!cache.contains_key(&key2));
} Hope this helps. |
I have a use case where the value being fetched through the cache may or may not exist. If it exists, the fetch may fail. Therefor I would like to be able to use some combination of
optionally_get_with
andtry_get_with
that would returnOption<Result<V>>
, and only caches typeV
if the future returnsSome(Ok(V))
.The text was updated successfully, but these errors were encountered: