Add HybridCache.GetOrCreateAsync overloads for dynamic setting of options#129048
Draft
svick wants to merge 9 commits into
Draft
Add HybridCache.GetOrCreateAsync overloads for dynamic setting of options#129048svick wants to merge 9 commits into
svick wants to merge 9 commits into
Conversation
…loads Introduce HybridCacheFactoryContext, a new type passed to the factory callback in GetOrCreateAsync, allowing the factory to dynamically influence cache entry options based on the result of the data fetch. The context exposes: - Expiration / LocalCacheExpiration: override entry lifetime (dotnet#121530) - Flags: override write-side cache flags, e.g. skip caching (dotnet#121530) - LocalCacheSize: set L1 cache entry size for MemoryCache SizeLimit (dotnet#114366) New virtual GetOrCreateAsync overloads mirror the existing key-shape family (string, ReadOnlySpan<char>, DefaultInterpolatedStringHandler) with both TState and no-TState variants. The default implementation wraps the context-aware factory and delegates to the existing abstract overload, preserving backward compatibility for existing HybridCache implementations. Implementations should override the new virtual method to honor context values. Contributes to dotnet#114366 Contributes to dotnet#121530 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add missing <summary> tag for LocalCacheExpiration and fix 'Gets or set' typo on Expiration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Clarify that DisableCompression is a write-side flag (honored from context) and DisableUnderlyingData is a read-side flag (ignored from context). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…entOptions and LocalCacheSize Implements API proposals in dotnet#114366 and dotnet#121530: - Rename HybridCacheFactoryContext to HybridCacheEntryContext. - Add HybridCacheEntryContext(HybridCacheEntryOptions currentOptions) constructor and CurrentOptions property. - Add LocalCacheSize init-only property to HybridCacheEntryOptions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
Tagging subscribers to this area: @dotnet/area-extensions-caching |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR expands Microsoft.Extensions.Caching.Hybrid.HybridCache with new GetOrCreateAsync overloads where the factory callback receives a mutable HybridCacheEntryOptions, enabling per-entry option adjustments at runtime (e.g., expiration, flags, local size). It also updates HybridCacheEntryOptions to support mutation tracking via Revision, adds LocalSize, and includes trimming and package-compat scaffolding for the new shape.
Changes:
- Make
HybridCacheEntryOptionsproperties mutable (get; set;), addLocalSize, and addRevisionmutation tracking (plus internal helpers). - Add new (virtual)
HybridCache.GetOrCreateAsyncoverloads whose factory receivesHybridCacheEntryOptions(string + NET-only key shapes). - Add trimming descriptor entries for internal helpers and add package compatibility suppressions for
init→setchanges.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/Microsoft.Extensions.Caching.Abstractions/src/Hybrid/HybridCacheEntryOptions.cs | Makes options mutable, adds LocalSize and Revision, plus internal clone/translation helpers. |
| src/libraries/Microsoft.Extensions.Caching.Abstractions/src/Hybrid/HybridCache.cs | Introduces options-aware GetOrCreateAsync overloads and a default implementation bridging to the existing abstract overload. |
| src/libraries/Microsoft.Extensions.Caching.Abstractions/src/ILLink/ILLink.Descriptors.LibraryBuild.xml | Preserves internal members accessed cross-assembly via UnsafeAccessor for trimming. |
| src/libraries/Microsoft.Extensions.Caching.Abstractions/src/CompatibilitySuppressions.xml | Adds package validation suppressions for the accessor-shape change. |
| src/libraries/Microsoft.Extensions.Caching.Abstractions/ref/Microsoft.Extensions.Caching.Abstractions.cs | Updates the public API contract for HybridCacheEntryOptions and adds the new string-key overloads. |
| src/libraries/Microsoft.Extensions.Caching.Abstractions/ref/Microsoft.Extensions.Caching.Abstractions.net10.cs | Adds NET-only key-shape overloads for the new factory signature. |
Comment on lines
+47
to
+67
| <DiagnosticId>CP0002</DiagnosticId> | ||
| <Target>M:Microsoft.Extensions.Caching.Hybrid.HybridCacheEntryOptions.set_Expiration(System.Nullable{System.TimeSpan})</Target> | ||
| <Left>lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll</Left> | ||
| <Right>lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll</Right> | ||
| <IsBaselineSuppression>true</IsBaselineSuppression> | ||
| </Suppression> | ||
| <Suppression> | ||
| <DiagnosticId>CP0002</DiagnosticId> | ||
| <Target>M:Microsoft.Extensions.Caching.Hybrid.HybridCacheEntryOptions.set_Flags(System.Nullable{Microsoft.Extensions.Caching.Hybrid.HybridCacheEntryFlags})</Target> | ||
| <Left>lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll</Left> | ||
| <Right>lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll</Right> | ||
| <IsBaselineSuppression>true</IsBaselineSuppression> | ||
| </Suppression> | ||
| <Suppression> | ||
| <DiagnosticId>CP0002</DiagnosticId> | ||
| <Target>M:Microsoft.Extensions.Caching.Hybrid.HybridCacheEntryOptions.set_LocalCacheExpiration(System.Nullable{System.TimeSpan})</Target> | ||
| <Left>lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll</Left> | ||
| <Right>lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll</Right> | ||
| <IsBaselineSuppression>true</IsBaselineSuppression> | ||
| </Suppression> | ||
| </Suppressions> No newline at end of file |
Comment on lines
+160
to
+169
| var factoryOptions = options is null ? new HybridCacheEntryOptions() : options.Clone(); | ||
|
|
||
| // Suppress writes in the inner call so we can perform a single, correct SetAsync afterwards | ||
| // using the options that the factory ultimately produced. | ||
| // This introduces some race conditions, but that's considered better than not honoring the factory's options. | ||
| var innerOptions = options is null ? new HybridCacheEntryOptions() : options.Clone(); | ||
| innerOptions.Flags = (innerOptions.Flags ?? HybridCacheEntryFlags.None) | ||
| | HybridCacheEntryFlags.DisableLocalCacheWrite | ||
| | HybridCacheEntryFlags.DisableDistributedCacheWrite; | ||
|
|
This was referenced Jun 5, 2026
Open
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.
Implements the API proposals approved in #121530 and #114366.
Changes
HybridCacheEntryOptions (mutable properties + revision tracking)
Expiration,LocalCacheExpiration, andFlagssetters are now public (previouslyinit), so factory callbacks can mutate the options instance they receive.LocalSizeproperty to control the size assigned to the local (L1) cache entry (e.g.MemoryCache.Size).Revisionproperty that increments on each property change, allowing implementations to detect whether a factory mutated the options.Clone()andToDistributedCacheEntryOptions()helpers used byDefaultHybridCacheviaUnsafeAccessor.HybridCache (options-aware factory overloads)
New virtual
GetOrCreateAsyncoverloads that take aFunc<…, HybridCacheEntryOptions, CancellationToken, ValueTask<T>>factory, mirroring the existing key-shape family (string,ReadOnlySpan<char>,DefaultInterpolatedStringHandler) with bothTStateand no-TStatevariants.The default implementation wraps the options-aware factory and delegates to the existing abstract overload, preserving backward compatibility for existing
HybridCacheimplementations. Implementations should override the new virtual to honor factory-supplied option values (including viaRevisionchecks for mutation detection).Trimming
Added
ILLink.Descriptors.LibraryBuild.xmlto preserve the internalCloneandToDistributedCacheEntryOptionsmembers. They are reached only cross-assembly viaUnsafeAccessorfromDefaultHybridCache, which the trimmer cannot see.API compatibility
Added
CompatibilitySuppressions.xmlfor theinit→setaccessor change on the existingHybridCacheEntryOptionsproperties.