Skip to content
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

Add get_or_insert_with method #20

Merged
merged 12 commits into from
Jul 8, 2021
Merged

Add get_or_insert_with method #20

merged 12 commits into from
Jul 8, 2021

Conversation

tatsuya6502
Copy link
Member

@tatsuya6502 tatsuya6502 commented Jun 26, 2021

This PR adds the get_or_insert_with and get_or_try_insert_with methods to sync and future caches in Moka. These methods ensure the key exists in the cache by inserting the return value from the given closure/future if the key does not exist. They also guarantee the closure/future is evaluated only once even if they are called from multiple threads/async tasks for the same key at the same time.

This feature was requested by #15.

Added

  • (API) Add get_or_insert_with and get_or_try_insert_with methods to the following cache implementations in Moka:
    • sync::Cache
    • sync::SegmentedCache
    • future::Cache
  • Add internal sync::value_initializer and future::value_initializer modules, containing cht::HashMap for waiters.

Fixes #15

- Implement get_or_insert_with and get_or_try_insert_with methods to future::Cache.
- Add unit test cases for these methods.
- Add async-lock crate to the dependencies for the future feature.
- Implement get_or_insert_with and get_or_try_insert_with methods to sync::Cache.
- Add unit test cases for these methods.
- Implement get_or_insert_with and get_or_try_insert_with methods to
sync::SegmentedCache.
- Add unit test cases for these methods.
Delay removing a waiter to avoid a race condition.
- Relax the restriction of the init closure (FnMut -> FnOnce).
- Write the API docs.
Refactoring: Rename internal methods.
Add Send + Sync + 'static bounds to the error type.
Remove duplicate `remove_waiter` calls.
Fix some source code comments.
@tatsuya6502 tatsuya6502 marked this pull request as ready for review July 8, 2021 13:44
Copy link
Member Author

@tatsuya6502 tatsuya6502 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging.

@tatsuya6502 tatsuya6502 merged commit 30f0537 into master Jul 8, 2021
@tatsuya6502 tatsuya6502 deleted the get_or_insert_with branch July 8, 2021 15:17
@ben-manes
Copy link

I don't know rust conventions, but Java's names in Map are quite nice.

  • computeIfAbsent(key, key -> value)
  • computeIfPresent(key, (key, oldValue) -> value)
  • compute(key, (key, oldValue) -> value
  • merge(key, value, (key, oldValue) -> newValue)

These are performed atomically and if null is returned then the mapping is removed. The names are nice as succinct and easy to understand. The three compute methods are very useful for advanced cases.

Caffeine's corre apis uses get for automatic loading, getIfPresent without, and offers an asMap() view for richer functionality (like compute or entry iterators). Since we highly prefer users to delegate to the cache for loading, we take the desirable get name and penalize the longer name getIfAbsent to dissuade usage. A lot of random functionality, like conditional entry removal or policy inspection, is hidden away under nested objects (asMap(), policy()) to provide the features while keeping the core interface simple to reduce the conceptual weight for learning a new library.

I don't know if any of that makes sense idiomatically for Rust. If so, you might consider reviewing our APIs for ideas before yours are finalized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature Request: Get or Insert Future
2 participants