moka icon indicating copy to clipboard operation
moka copied to clipboard

Update Key With One Evaluation of the `init` Future

Open ShiromMakkad opened this issue 7 months ago • 12 comments

I'm working on a refresh ahead cache that's a wrapper around a moka cache. This cache will need to make update on its keys every x minutes, usually by calling an API. I don't want there to be multiple requests to update a key. Instead I want the requests to be coalesced into one.

From moka::future::OwnedKeySelector::or_insert_with:

This method guarantees that concurrent calls on the same not-existing entry are coalesced into one evaluation of the init future. Only one of the calls evaluates its future (thus returned entry’s is_fresh method returns true), and other calls wait for that future to resolve (and their is_fresh return false).

However, this only runs when the key doesn't exist. I want to update its value. To do this, I'd use moka::future::OwnedKeySelector::and_try_compute_with. But it says,

This method guarantees that concurrent calls on the same key are executed serially. That is, and_try_compute_with calls on the same key never run concurrently. The calls are serialized by the order of their invocation. It uses a key-level lock to achieve this.

I'm looking for a function that has the same behavior as and_try_compute_with but the same concurrency as or_insert_with. Did I miss something when reading the docs or is there not a way to do this?

Right now, I'm simply removing the key before running the closure, but this resets the TTL on the value. I don't want to do that. Also, one question about this approach: Can multiple calls to remove at the same time return copies of the value, or will only one call get the value and all others get None back?

ShiromMakkad avatar Jun 27 '24 17:06 ShiromMakkad