Replace custom ICacheStore with FusionCache#111
Merged
antosubash merged 3 commits intomainfrom Apr 15, 2026
Merged
Conversation
Delete the entire framework/SimpleModule.Core/Caching/ tree (8 files, 461 LOC) and its test (MemoryCacheStoreTests, 300 LOC). Stampede protection, per-key locking, key tracking, and prefix removal are all provided natively by ZiggyCreatures.FusionCache 2.6.0 — the custom abstraction added no value over the upstream library. Migrate the 11 call sites across Settings, FeatureFlags, Localization, Marketplace, Permissions, and Tenants to IFusionCache. TryGet + Set pairs become GetOrSetAsync where the factory unconditionally caches its result; the LocaleResolutionMiddleware keeps its TryGet/Set pattern because it conditionally caches (explicit user setting yes, fallback no). No module csproj needs editing — FusionCache flows transitively from SimpleModule.Core. RemoveByPrefixAsync was only used by the deleted test, so no prefix→tag conversion is required in production code. Net: -774 LOC. All 1207 tests green.
The Action<FusionCacheEntryOptions> setup-action overload passed to GetOrSetAsync/SetAsync is invoked on every call (even on cache hits), so 'options => options.Duration = X' allocates a new closure each call. On hot paths this shows up: - PermissionClaimsTransformation.TransformAsync runs per authenticated request through the auth pipeline - HostNameTenantResolver.ResolveAsync runs per request - LocaleResolutionMiddleware runs per request (SetAsync only fires on miss, but still worth cleaning up for consistency) Replace the TimeSpan-field-plus-lambda pattern with a pre-built FusionCacheEntryOptions instance that is passed directly to the cache API. For services whose durations come from IOptions<T>, initialize a readonly instance field from the primary-constructor parameter so the instance is built once per service lifetime rather than per call. Also drop redundant 'var duration = ...' locals and the 'opts => opts.Duration = ...' pattern across every call site; the pre-built options instance eliminates both concerns. FusionCache internally calls Duplicate() on the passed options before applying per-call modifications, so sharing an instance across calls is safe. All 1207 tests pass.
Deploying simplemodule-website with
|
| Latest commit: |
7079d51
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://bd531668.simplemodule-website.pages.dev |
| Branch Preview URL: | https://feature-condescending-bassi.simplemodule-website.pages.dev |
…-bassi # Conflicts: # modules/FeatureFlags/src/SimpleModule.FeatureFlags/FeatureFlagService.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replace the custom
framework/SimpleModule.Core/Caching/abstraction (8 files, 461 LOC) with ZiggyCreatures.FusionCache 2.6.0. The custom cache provided in-processIMemoryCachewith per-key stampede locking, prefix-based removal, and key tracking — all of which FusionCache provides natively with more battle-testing.SimpleModule.CoreRemoveByPrefixAsyncwas only used in the deleted test — no prefix→tag conversion needed in productionMigration map
ICacheStoreIFusionCacheGetOrCreateAsync(key, factory, options)GetOrSetAsync(key, factory, opts => opts.Duration = ...)TryGetAsync<T>+SetAsyncpairs (unconditional)GetOrSetAsync(single call)TryGetAsync<T>+SetAsyncpairs (conditional)TryGetAsync+SetAsync(LocaleResolutionMiddleware)CacheEntryOptions.Expires(duration)opts => opts.Duration = durationCacheKey.Compose(...)(1 site)AddSimpleModuleCaching()AddFusionCache().WithDefaultEntryOptions(...)Stampede prevention is built into FusionCache's
StandardMemoryLocker— no per-keySemaphoreSlimmanagement required.Test plan
dotnet build— 0 warnings, 0 errorsdotnet test— 1207 passed, 0 failed, 1 skipped (pre-existing)npm run check— biome + typecheck + i18n + validate-pages all greennpm run build— all 19 modules + ClientApp build cleannpm run test:smoke— 68/68 E2E smoke tests passICacheStore,MemoryCacheStore,CacheEntryOptions,CacheResult,CacheKey.Compose,AddSimpleModuleCachinganywhere in the repoPart of a series
This is PR 1 of 3 replacing custom framework code with trusted OSS libraries:
ValidationBuilder→ FluentValidationIEventBus→ WolverineEach PR is independent and can merge in any order.