[PM-32069] Add ExtendedProviderAbilityCacheService#7447
Conversation
|
Fixed Issues (3)Great job! The following issues were fixed in this Pull Request
|
Bitwarden Claude Code ReviewOverall Assessment: APPROVE This PR adds Code Review DetailsNo new findings. The active discussion threads on singleton vs scoped registration and cache key formatting are already being addressed by the author and reviewers. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #7447 +/- ##
==========================================
- Coverage 63.27% 58.87% -4.40%
==========================================
Files 2074 2076 +2
Lines 91391 91424 +33
Branches 8140 8143 +3
==========================================
- Hits 57825 53829 -3996
- Misses 31565 35672 +4107
+ Partials 2001 1923 -78 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
I looked at the failed Build Docker images (SeederApi, ./util, linux/amd64, linux/arm64, true) job. It looks like a permission issue when logging into Azure. I don't think this is related to my change. |
|
Added @jrmccannon as a reviewer because he has context working with the organization cache. @BTreston, feel free to add feedback, though. |
jrmccannon
left a comment
There was a problem hiding this comment.
Just a few things @eliykat had mentioned to me and we should be consistent across the two ability caches.
| services.AddOptionality(); | ||
| services.AddTokenizers(); | ||
|
|
||
| services.AddDistributedCache(globalSettings); |
There was a problem hiding this comment.
Did you run into an error with this?
I would say there's a chance this would error as it attempts to add more than 1 Distributed cache. It is In several startup files.
| services.AddExtendedCache(ExtendedProviderAbilityCacheService.CacheName, globalSettings); | ||
| services.AddSingleton<IProviderAbilityCacheService, ExtendedProviderAbilityCacheService>(); |
There was a problem hiding this comment.
Move this to an extension method similar to OrgAbility.
| services.AddExtendedCache(ExtendedProviderAbilityCacheService.CacheName, globalSettings); | ||
| services.AddSingleton<IProviderAbilityCacheService, ExtendedProviderAbilityCacheService>(); |
There was a problem hiding this comment.
Use extension method instead
| namespace Bit.Core.Test.AdminConsole.AbilitiesCache; | ||
|
|
||
| [SutProviderCustomize] | ||
| public class ExtendedProviderAbilityCacheServiceTests |
There was a problem hiding this comment.
Is this testing anything meaningful? I'd say remove these unit tests and replace with some integration tests to validate.
| public async Task<ProviderAbility?> GetProviderAbilityAsync(Guid providerId) | ||
| { | ||
| return await cache.GetOrSetAsync<ProviderAbility?>( | ||
| $"{providerId}", |
There was a problem hiding this comment.
@jrmccannon this is also a different way of constructing the cache key compared to yours - while the guid should be unique, the prefix seems like better practice to me if required to namespace it. Or does the CacheName already namespace it? I don't mind, as long as the approach is consistent.
There was a problem hiding this comment.
We should update the Org cache since I think not having unnecessary prefixes is a better path.
| public static IServiceCollection AddProviderAbilityCache(this IServiceCollection services, | ||
| GlobalSettings globalSettings) => | ||
| services.AddExtendedCache(ExtendedProviderAbilityCacheService.CacheName, globalSettings) | ||
| .AddSingleton<IProviderAbilityCacheService, ExtendedProviderAbilityCacheService>(); |
There was a problem hiding this comment.
💡 Suggestion (non-blocking): This registers as AddSingleton, while the analogous OrganizationAbilityServiceCollectionsExtension uses AddScoped. Both work correctly since all dependencies (IFusionCache, IProviderRepository) are singletons, but the inconsistency is worth calling out — was this an intentional change from the org pattern?
There was a problem hiding this comment.
@jrmccannon , I think we should use AddSingleton for this since it’s a stateless service. Let me know what you think.
I know you have a PR open for the multiple use case. I can add a request for changes on that one, if you’d like.
| return await cache.GetOrSetAsync<ProviderAbility?>( | ||
| $"{providerId}", | ||
| async _ => await providerRepository.GetAbilityAsync(providerId) | ||
| ); |
There was a problem hiding this comment.
💡 Suggestion (non-blocking): The cache key here is a bare GUID ($"{providerId}"), while the org equivalent uses a prefixed, formatted key ($"org-ability:{organizationId:N}"). Since these live in separate named caches there's no collision risk, but a prefixed key like $"provider-ability:{providerId:N}" would improve consistency and make cache entries easier to identify when debugging.
| return await cache.GetOrSetAsync<ProviderAbility?>( | |
| $"{providerId}", | |
| async _ => await providerRepository.GetAbilityAsync(providerId) | |
| ); | |
| return await cache.GetOrSetAsync<ProviderAbility?>( | |
| $"provider-ability:{providerId:N}", | |
| async _ => await providerRepository.GetAbilityAsync(providerId) | |
| ); |
…iceTests.cs Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
|
jrmccannon
left a comment
There was a problem hiding this comment.
Looks good. I took recommendations from this and made mine consistent as well.
eliykat
left a comment
There was a problem hiding this comment.
Nothing more needed from me, you're all over it 👍






🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-32069
https://bitwarden.atlassian.net/browse/PM-32112
📔 Objective
📸 Screenshots
This code isn't wired up yet, so we can't manually test it, but I feel like the automated test coverage is sufficient.