Conversation
…ache interface Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/0a2b82c7-2685-4e3c-9574-b730373ab8d4 Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
…cFactoryAsyncCache with unit tests Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/ecb8a7bd-bccd-4ac6-a5ac-05912949a409 Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds async alternate-key lookup discovery to IAsyncCache<K,V> (net9+) to mirror the existing ICache alternate-lookup pattern, and wires implementations/docs across LRU/LFU caches plus the atomic async decorator.
Changes:
- Add
GetAsyncAlternateLookup<TAlternateKey>()/TryGetAsyncAlternateLookup<TAlternateKey>()default interface methods toIAsyncCache<K,V>(net9+). - Update LRU/LFU implementations’ XML docs to
///<inheritdoc/>now that these methods are interface members. - Implement async alternate lookup in
AtomicFactoryAsyncCacheand add unit tests for basic lookup/update/remove andGetOrAddAsyncmiss/hit behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| BitFaster.Caching/IAsyncCache.cs | Adds net9+ async alternate-lookup methods as default interface members (mirrors ICache). |
| BitFaster.Caching/Lru/ConcurrentLruCore.cs | Switches async alternate-lookup method docs to inherit interface docs. |
| BitFaster.Caching/Lru/ClassicLru.cs | Switches async alternate-lookup method docs to inherit interface docs. |
| BitFaster.Caching/Lfu/ConcurrentLfuCore.cs | Switches async alternate-lookup method docs to inherit interface docs. |
| BitFaster.Caching/Lfu/ConcurrentLfu.cs | Switches async alternate-lookup method docs to inherit interface docs. |
| BitFaster.Caching/Lfu/ConcurrentTLfu.cs | Switches async alternate-lookup method docs to inherit interface docs. |
| BitFaster.Caching/Atomic/AtomicFactoryAsyncCache.cs | Adds IAsyncCache async alternate-lookup implementation by wrapping inner IAlternateLookup and translating AsyncAtomicFactory values. |
| BitFaster.Caching.UnitTests/Atomic/AtomicFactoryAsyncCacheAsyncAlternateLookupTests.cs | Adds tests covering comparer compatibility and core async alternate-lookup operations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Task<V> task = valueFactory(key, factoryArgument); | ||
| return factory.GetValueAsync(default(K)!, static (_, t) => t, task); | ||
| } |
There was a problem hiding this comment.
Same issue as the non-TArg overload: invoking valueFactory(key, factoryArgument) eagerly means concurrent callers on a cache miss will start multiple tasks, but only one will be consumed by AsyncAtomicFactory initialization; the remainder can cause duplicated side effects and unobserved exceptions. Consider moving the valueFactory invocation into the inner.GetOrAdd add-path so it executes once, then have all callers await the shared initialization result.
|
@copilot merge with main and fix merge conflicts. Ensure comments in the PR are addressed. |
Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
…omicFactory double-check Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/172d9137-e999-4a1e-b572-963a2f919311 Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
Merged with main in 2ef7671 (no conflicts). Addressed the reviewer comments about After merging #752, the factory signature changed from |
|
|
||
| private ValueTask<V> GetOrAddAsyncSlow(TAlternateKey key, Func<K, Task<V>> valueFactory) | ||
| { | ||
| var box = new KeyBox<K>(); |
There was a problem hiding this comment.
This appears to be introduced because ICache does not expose comparer, without it there is no way to create an instance of K from TAlternateKey. The LLM thinks it can capture K by invoking the value factory.
This means the cache must expose the comparer somehow.
|
@copilot merge the latest from main, then address the review comment in AtomicFactoryAsyncCache.cs. Instead of capturing the key, use the cache comparer property to create a key instance from the alternate key. |
…into copilot/add-getasyncalternatelookup-methods Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
…o K conversion Agent-Logs-Url: https://github.com/bitfaster/BitFaster.Caching/sessions/c7c00ddc-3647-483f-bec1-2611fa2cc6e5 Co-authored-by: bitfaster <12851828+bitfaster@users.noreply.github.com>
Merged latest main in 7af9ef6 (includes #754 Comparer property). Replaced the |
Summary
Adds
GetAsyncAlternateLookup<TAlternateKey>()andTryGetAsyncAlternateLookup<TAlternateKey>()methods to theIAsyncCache<K, V>interface, gated behind#if NET9_0_OR_GREATER. This mirrors the existingGetAlternateLookup/TryGetAlternateLookuppattern already present onICache<K, V>.Changes
IAsyncCache.cs: Added default interface methodsGetAsyncAlternateLookupandTryGetAsyncAlternateLookupwiththrow new NotSupportedException()defaults, matching theICachepattern includingCS8714pragma suppressionConcurrentLruCore.cs,ClassicLru.cs,ConcurrentLfu.cs,ConcurrentTLfu.cs,ConcurrentLfuCore.cs: Updated existing method XML doc comments to use///<inheritdoc/>since they now implement the interface methodsAtomicFactoryAsyncCache.cs: ImplementedGetAsyncAlternateLookupandTryGetAsyncAlternateLookupwith an internalAlternateLookup<TAlternateKey>struct that wraps the inner cache'sIAlternateLookup<TAlternateKey, K, AsyncAtomicFactory<K, V>>and translates values. The struct stores anIAlternateEqualityComparer<TAlternateKey, K>obtained fromcache.Comparer(added in Add net9 Comparer property to cache interfaces and implementations #754) and usescomparer.Create(key)inGetOrAddAsyncto produce the actualKfromTAlternateKey, then delegates toAsyncAtomicFactory.GetValueAsync(actualKey, valueFactory)which ensures exactly-once initialization through its DoubleCheck mechanism. ATryGetfast path avoids the slow path allocation on cache hits.Testing
All 1486 unit tests pass on net9.0, including 9 new tests in
AtomicFactoryAsyncCacheAsyncAlternateLookupTestscovering compatible/incompatible comparer handling, TryGet miss, TryRemove hit/miss, TryUpdate, AddOrUpdate, and bothGetOrAddAsyncoverloads verifying miss+hit semantics. Builds succeed across all target frameworks (netstandard2.0, netcoreapp3.1, net6.0, net9.0).