-
-
Notifications
You must be signed in to change notification settings - Fork 73
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
[help] Conditionally disabling the cache, and logging when data retrieved from cache #229
Comments
Hi. I think there are couple of ways to achieve. The first one is more straightforward than the other but inserts a value into the cache even when testing, so may be a bit waste? pub fn get_with(&self, key: K, init: impl FnOnce() -> V) -> V {
self.cache
.entry(key)
.or_insert_with_if(init, |_v| {
#[cfg(any(test, feature = "test"))]
{
tracing::warn!("caching disabled during tests");
// Return `true` to ignore and replace the cached value
// with a freshly computed one.
return true;
}
#[allow(unreachable_code)]
{
false
}
})
.into_value()
} The second one is hackey but does not insert a value into the cache when testing. pub fn get_with(&self, key: K, init: impl FnOnce() -> V) -> V {
// This will evaluate the `init` when the key does not exist.
let result = self.cache
.try_get_with(key, || {
let v = init();
#[cfg(any(test, feature = "test"))]
{
tracing::warn!("caching disabled during tests");
// This will not insert the value into the cache.
return Err(v);
}
#[allow(unreachable_code)]
{
// This will insert the value into the cache.
Ok(v) as Result<V, V>
}
});
match result {
Ok(v) => v,
// V is wrapped in an Arc, so we need to deref and clone it.
Err(arc_v) => (*arc_v).clone(),
}
} For the above particular case for testing, you can also do another way; to set the max capacity of the cache to 0 when testing. It will make the cache not to cache anything, but will still compute the value. Note that there is a known issue with such a configuration. Please see the workaround in the description of #230. |
That's very interesting! and thanks for the swift reply. While it does prohibit the cache from being used during tests, I still see no way to have a behaviour be invoked when something is retrieved from the cache, however :( |
Perhaps, what you want is #227,
You can log inside the closure, or log after returning from The return value from
I have not started to implement #227 yet, and feedback on the spec will be welcome! |
Maybe you are talking that I did not have the following debug log in my example? #[allow(unreachable_code)]
self.0.get(key).map(|v| {
tracing::debug!(?key, "retrieved from cache");
v
}) |
If so, the following will do? pub fn get_with(&self, key: K, init: impl FnOnce() -> V) -> V {
let entry = self.cache
.entry_by_ref(&key)
.or_insert_with_if(init, |_v| {
#[cfg(any(test, feature = "test"))]
{
tracing::warn!("caching disabled during tests");
// Return `true` to ignore and replace the cached value
// with a freshly computed one.
return true;
}
#[allow(unreachable_code)]
{
false
}
});
if !entry.is_fresh() {
tracing::debug!(key, "retrieved from cache");
}
entry.into_value()
} |
Are you happy with above? Or, you want the following?
|
This will require #227. pub fn get_with(&self, key: K, init: impl FnOnce() -> V) -> V {
let (maybe_entry, _) = self.cache
.entry_by_ref(&key)
.and_compute(move |maybe_v| {
if let Some(v) = maybe_v {
#[cfg(any(test, feature = "test"))]
{
// A value already exists, but replace it with a new value.
tracing::warn!("caching disabled during tests");
return Op::Put(init());
}
#[allow(unreachable_code)]
{
// A value already exists, and keep it.
tracing::debug!(key, "retrieved from cache");
Op::Nop
}
} else {
// Value does not exist, so insert a new value.
Op::Put(init())
}
});
maybe_entry.unwrap().into_value()
} |
Great, thank you! Sorry for my slow reply, got side tracked with other issues, but finally got around to this :) In the end, my code is now rather WET because the I also noticed, that if I wanted to impl this for And I still would need to build, maintain and test, every way in which a retrieval from the cache is made, therefore a hook into all cache retrievals that can be configured in the builder would be ideal, but, I've just noticed the |
Hello!
In my code I have built a wrapper around Moka, such that I can have hooks that occur before any retrieval from cache
e.g.
But then get_with becomes sub-optimal because:
I looked into the new Entry API in v 0.10.0 but I don't think that can help me here.
I think I'm asking for an enhancement where we can pass the builder a closure that gets called pre every cache retrieval.
But maybe with your superior wisdom you can see what I'm trying to do better and suggest an alternative?
Many thanks!
The text was updated successfully, but these errors were encountered: