Skip to content
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

HybridCache support for Tuples #5716

Closed
1 task done
mrazvanalex opened this issue Dec 2, 2024 · 2 comments · Fixed by #5979
Closed
1 task done

HybridCache support for Tuples #5716

mrazvanalex opened this issue Dec 2, 2024 · 2 comments · Fixed by #5979
Labels
area-caching-hybrid bug This issue describes a behavior which is not expected - a bug. work in progress 🚧

Comments

@mrazvanalex
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

I've been trying to implement a system based on eTag to return a 304 in case the existing resource has not changed in the Database.

I have a HybridCache instance working alongside this ETag in the API layer. When returning a tuple ( obj, string ) from the cache, they are returned as null, even if values are attributed in the service call. Provided sample code:

var tags = new List<string> { "test" };
var entryOptions = new HybridCacheEntryOptions
{
    Expiration = TimeSpan.FromMinutes(1),
    LocalCacheExpiration = TimeSpan.FromMinutes(1)
};

var clientETag = httpContext.Request.Headers["If-None-Match"].FirstOrDefault();
var  (result, eTag) = await _cache.GetOrCreateAsync($"identifier", async get =>
{
    var (result, eTag) = await _companyService.GetPaginatedBillsAasync(companyId, filter, clientETag); // values retrieved from service 
    return  (result, eTag); // values are attributed.
}, entryOptions, tags); // values are still shown in breakpoints
// After reaching this point, result and eTag are now null.

if (result == null) // Here result is always null. 
{
    return Results.StatusCode(304); 
}

Describe the solution you'd like

I expect the tuple to retain it's value after the Func has finished it's execution.

Additional context

@BrennanConroy BrennanConroy transferred this issue from dotnet/aspnetcore Dec 2, 2024
@konjac
Copy link

konjac commented Jan 9, 2025

Actually, Tuple is working but ValueTuple is not. A workaround is to use Tuple.Create(result, eTag) explicitly.

The problem is DefaultHybridCache serializes/deserializes the cache item using System.Text.Json.Serializer with JsonSerializerOptions.Default. The default serializer option does not support fields in ValueTuple. Tuple stores items as properties, so it can work.

var valueTuple = ValueTuple.Create<int, string>(123, "string");
var tuple = Tuple.Create<int, string>(123, "string");
var optionsIncludeFields = new JsonSerializerOptions()
{
	IncludeFields = true
};
string tupleJsonString = JsonSerializer.Serialize(tuple, JsonSerializerOptions.Default);
string valueTupleJsonString = JsonSerializer.Serialize(valueTuple, JsonSerializerOptions.Default);
string valueTupleJsonStringIncludeFields = JsonSerializer.Serialize(valueTuple, optionsIncludeFields);
Console.WriteLine("Vuple      serialized with default:\t{0}", tupleJsonString);
Console.WriteLine("ValueTuple serialized with default:\t{0}", valueTupleJsonString);
Console.WriteLine("ValueTuple serialized with fields: \t{0}", valueTupleJsonStringIncludeFields);

//Output
//Tuple      serialized with default:    {"Item1":123,"Item2":"string"}
//ValueTuple serialized with default:    {}
//ValueTuple serialized with fields:     {"Item1":123,"Item2":"string"}

@mgravell mgravell added the bug This issue describes a behavior which is not expected - a bug. label Feb 26, 2025
@mgravell
Copy link
Member

In addition to #5827, I propose that we detect value-tuples and use a shared field-enabled options instance; we can't do that globally without changing behaviour, but I think it is the correct choice for value-tuples.

mgravell added a commit to mgravell/extensions that referenced this issue Feb 26, 2025
- support value-tuples (requires field mode)
- support global custom JSON options via keyed DI

fix dotnet#5716
fix dotnet#5827
@github-actions github-actions bot locked and limited conversation to collaborators Mar 30, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-caching-hybrid bug This issue describes a behavior which is not expected - a bug. work in progress 🚧
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants