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

Open
1 task done
mrazvanalex opened this issue Dec 2, 2024 · 1 comment
Open
1 task done

HybridCache support for Tuples #5716

mrazvanalex opened this issue Dec 2, 2024 · 1 comment

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"}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants