Skip to content

[PM-32069] Add ExtendedProviderAbilityCacheService#7447

Merged
JimmyVo16 merged 12 commits intomainfrom
ac/pm-32069/add-extended-provider-cache
Apr 17, 2026
Merged

[PM-32069] Add ExtendedProviderAbilityCacheService#7447
JimmyVo16 merged 12 commits intomainfrom
ac/pm-32069/add-extended-provider-cache

Conversation

@JimmyVo16
Copy link
Copy Markdown
Contributor

@JimmyVo16 JimmyVo16 commented Apr 10, 2026

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-32069
https://bitwarden.atlassian.net/browse/PM-32112

📔 Objective

  1. Add extended cache for the provider service (IProviderAbilityCacheService).
  2. Inject IProviderAbilityCacheService into FeatureRoutedCacheService behind a feature flag.
  3. Add unit tests.

📸 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.

@JimmyVo16 JimmyVo16 self-assigned this Apr 10, 2026
@JimmyVo16 JimmyVo16 added the ai-review Request a Claude code review label Apr 10, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 10, 2026

Logo
Checkmarx One – Scan Summary & Details8903f213-00a0-4634-853e-e308455ba11d


Fixed Issues (3) Great job! The following issues were fixed in this Pull Request
Severity Issue Source File / Package
MEDIUM CSRF src/Api/KeyManagement/Controllers/AccountsKeyManagementController.cs: 145
MEDIUM CSRF src/Api/KeyManagement/Controllers/AccountsKeyManagementController.cs: 97
MEDIUM CSRF src/Api/KeyManagement/Controllers/AccountsKeyManagementController.cs: 173

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 10, 2026

Bitwarden Claude Code Review

Overall Assessment: APPROVE

This PR adds ExtendedProviderAbilityCacheService behind the ProviderAbilityExtendedCache feature flag, mirroring the existing organization ability cache pattern. The implementation includes a new IProviderAbilityCacheService interface, a DI registration extension method, feature flag routing in FeatureRoutedCacheService, and both unit and integration tests. The code follows established codebase patterns and provides appropriate test coverage for all three routed operations (get, upsert, delete).

Code Review Details

No 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
Copy link
Copy Markdown

codecov Bot commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 58.87%. Comparing base (28902ac) to head (c600a4d).
⚠️ Report is 6 commits behind head on main.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JimmyVo16 JimmyVo16 marked this pull request as ready for review April 14, 2026 14:39
@JimmyVo16 JimmyVo16 requested review from a team as code owners April 14, 2026 14:39
@JimmyVo16 JimmyVo16 requested a review from BTreston April 14, 2026 14:39
@JimmyVo16
Copy link
Copy Markdown
Contributor Author

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.

@JimmyVo16
Copy link
Copy Markdown
Contributor Author

Added @jrmccannon as a reviewer because he has context working with the organization cache. @BTreston, feel free to add feedback, though.

@JimmyVo16 JimmyVo16 requested a review from jrmccannon April 15, 2026 13:37
Copy link
Copy Markdown
Contributor

@jrmccannon jrmccannon left a comment

Choose a reason for hiding this comment

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

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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Comment on lines +298 to +299
services.AddExtendedCache(ExtendedProviderAbilityCacheService.CacheName, globalSettings);
services.AddSingleton<IProviderAbilityCacheService, ExtendedProviderAbilityCacheService>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Move this to an extension method similar to OrgAbility.

Comment thread src/Events/Startup.cs Outdated
Comment on lines +87 to +88
services.AddExtendedCache(ExtendedProviderAbilityCacheService.CacheName, globalSettings);
services.AddSingleton<IProviderAbilityCacheService, ExtendedProviderAbilityCacheService>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use extension method instead

namespace Bit.Core.Test.AdminConsole.AbilitiesCache;

[SutProviderCustomize]
public class ExtendedProviderAbilityCacheServiceTests
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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}",
Copy link
Copy Markdown
Member

@eliykat eliykat Apr 16, 2026

Choose a reason for hiding this comment

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

@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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes per @justindbaur's comment

image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We should update the Org cache since I think not having unnecessary prefixes is a better path.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the info! I agree.

public static IServiceCollection AddProviderAbilityCache(this IServiceCollection services,
GlobalSettings globalSettings) =>
services.AddExtendedCache(ExtendedProviderAbilityCacheService.CacheName, globalSettings)
.AddSingleton<IProviderAbilityCacheService, ExtendedProviderAbilityCacheService>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 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?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@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.

Comment on lines +18 to +21
return await cache.GetOrSetAsync<ProviderAbility?>(
$"{providerId}",
async _ => await providerRepository.GetAbilityAsync(providerId)
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 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.

Suggested change
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)
);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Comment thread test/Core.Test/Services/Implementations/FeatureRoutedCacheServiceTests.cs Outdated
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@jrmccannon jrmccannon left a comment

Choose a reason for hiding this comment

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

Looks good. I took recommendations from this and made mine consistent as well.

Copy link
Copy Markdown
Member

@eliykat eliykat left a comment

Choose a reason for hiding this comment

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

Nothing more needed from me, you're all over it 👍

@JimmyVo16 JimmyVo16 merged commit 914d412 into main Apr 17, 2026
64 checks passed
@JimmyVo16 JimmyVo16 deleted the ac/pm-32069/add-extended-provider-cache branch April 17, 2026 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Request a Claude code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants