-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Add IOutputCacheBufferWriterStore #48854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for contacting us. We're moving this issue to the |
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
Why is |
I'm not super enthusiastic about the I'm wondering whether it would be better to put two new Get and Set methods on the new interface and leave the original one alone. |
@mitchdenny to make it explicit; the Re putting them both on the same interface: probably fine here. Any implementation that is perfectly happy to return Maybe |
@mitchdenny TryGetAsync? + public interface IOutputCacheBufferStore : IOutputCacheStore
+ {
+ ValueTask<bool> TryGetAsync(string key, IBufferWriter<byte> destination, CancellationToken cancellationToken);
+ ValueTask SetAsync(string key, ReadOnlySequence<byte> value, ReadOnlyMemory<string> tags, TimeSpan validFor, CancellationToken cancellationToken);
+ } |
API Review Notes:
API Approved! // Microsoft.AspNetCore.OutputCaching.dll
namespace Microsoft.AspNetCore.OutputCaching;
+ public interface IOutputCacheBufferStore : IOutputCacheStore
+ {
+ ValueTask<bool> TryGetAsync(string key, PipeWriter destination, CancellationToken cancellationToken);
+ ValueTask SetAsync(string key, ReadOnlySequence<byte> value, ReadOnlyMemory<string> tags, TimeSpan validFor, CancellationToken cancellationToken);
+ }
// Microsoft.Extensions.Caching.StackExchangeRedis.dll
namespace Microsoft.Extensions.Caching.StackExchangeRedis;
public static class StackExchangeRedisCacheServiceCollectionExtensions
{
+ public static IServiceCollection AddStackExchangeRedisOutputCache(
+ this IServiceCollection services, Action<RedisCacheOptions> setupAction)
} |
@mgravell Can this be closed now? |
@adityamandaleeka I honestly don't know :) last time I closed an API one down, it was too soon and caused problems - maybe @halter73 can tell me the right time to close them? |
We can definitely close this now that all the changes are in, but it helps to leave a new comment to indicate what has changed since June 20th when this API was approved. Editing comments is not ideal for when people come back and want to see how we arrived at our API decisions. Here's what @mgravell wrote in the API review email thread about why #50457 which added the new Microsoft.AspNetCore.OutputCaching.StackExchangeRedis NuGet package was necessary:
RC2 API Update// Microsoft.Extensions.Caching.StackExchangeRedis.dll
namespace Microsoft.Extensions.Caching.StackExchangeRedis;
public static class StackExchangeRedisCacheServiceCollectionExtensions
{
- public static IServiceCollection AddStackExchangeRedisOutputCache(
- this IServiceCollection services, Action<RedisCacheOptions> setupAction)
}
+ // Microsoft.AspNetCore.OutputCaching.StackExchangeRedis.dll (NuGet net8.0 only)
+ namespace Microsoft.AspNetCore.OutputCaching.StackExchangeRedis;
+ public sealed class RedisOutputCacheOptions
+ {
+ public RedisOutputCacheOptions();
+
+ public string? Configuration { get; set; }
+ public ConfigurationOptions? ConfigurationOptions { get; set; }
+ public Func<Task<IConnectionMultiplexer>>? ConnectionMultiplexerFactory { get; set; }
+ public string? InstanceName { get; set; }
+ public Func<ProfilingSession>? ProfilingSession { get; set; }
+ }
namespace Microsoft.Extensions.DependencyInjection;
+ public static class StackExchangeRedisOutputCacheServiceCollectionExtensions
+ {
+ public static IServiceCollection AddStackExchangeRedisOutputCache(this IServiceCollection services, Action<RedisOutputCacheOptions> setupAction);
+ } Note: All the public properties on the new As for why we didn't just use the existing options type from the StackExchangeRedis package, see the discussion at #50457 (comment). tl;dr: there was some discussion about independently configuring a redis-back IDistributedCache and IOutputCache, but the main thing seems to be we didn't want to add a Microsoft.Extensions.Caching.StackExchangeRedis dependency to the new Microsoft.AspNetCore.OutputCaching.StackExchangeRedis package for just the options type. |
Ideally for preview 6...
Background and Motivation
We wish to implement an official SE.Redis output cache implementation.
The existing
IOutputCacheStore
API isbyte[]
-focused, which is fine for the in-process implementation which constantly returns the samebyte[]
, but is hugely suboptimal for out-of-process implementations, as we would have to return a right-sizedbyte[]
every call (in either direction), causing GC load. Additionally, since output-cache is an entire page load plus headers, this can easily be large enough to spill into LOH.Context: #48450
IMPORTANT: this API was approved for RC6, but an unforeseen problem arose (also #50402) where-by this change added a framework reference into a previously non-framework-reference OOB package; this is undesirable, so a secondary change is proposed to resolve this. The obsolete parts of this proposal have been
struck, and the new changes are in italics.For this, we propose three things:
SetAsync
method similar to the existing, but takingReadOnlySequence<byte>
instead ofbyte[]
; this API to be implemented in the existingIOutputCacheStore
interface as a DIM, to avoid back-compat problemsIOutputCacheBufferWriterStore
which extendsIOutputCacheStore
(same assembly/namespace), allowing implementations to optionally use a newGetAsync
API that takes anIBufferWriter<byte>
- thus allowing implementations to pass data to the consumer while site-stepping the topic of "data lifetime" : the receiver can pass a recycling-enabled buffer-writer, and the cache implementation does not need to know about those details - it just asks for space to write data, and writesin the existing Microsoft.Extensions.Caching.StackExchangeRedis OOB packagein a new Microsoft.AspNetCore.OutputCaching.StackExchangeRedis OOB packageProposed API
This second interface is optional / separate because not all types will wish to opt in; in particular, in the case of the existing in-proc implementation, it will be preferable to just keep returning the existing
byte[]
; as such, the output cache middleware will test for this API and use the most appropriate.Additionally, to implement the SE.Redis cache, we propose the addition of
package: `Microsoft.Extensions.Caching.StackExchangeRedis` (pre-existing) type `StackExchangeRedisCacheServiceCollectionExtensions` (pre-existing)
package:
Microsoft.AspNetCore.OutputCaching.StackExchangeRedis
(new)type
Microsoft.AspNetCore.OutputCaching.StackExchangeRedis
(new)where
RedisOutputCacheOptions
is a new clone of the existingRedisCacheOptions
, but in the new package/namespace (otherwise: 1-1 feature parity withRedisCacheOptions
):which is the new API to register SE.Redis into output cache
Alternatives considered
GetAsync
API that returns some kind of "data with lifetime" - however, there's no good metaphor for this, and it pushes the buffer management into each individual buffer implementation, rather than having one buffer implementation and having the cache implementations just worry about cacheThe text was updated successfully, but these errors were encountered: