diff --git a/src/Libraries/Microsoft.Extensions.AI/CachingHelpers.cs b/src/Libraries/Microsoft.Extensions.AI/CachingHelpers.cs index 102fc86b138..3b5f5531755 100644 --- a/src/Libraries/Microsoft.Extensions.AI/CachingHelpers.cs +++ b/src/Libraries/Microsoft.Extensions.AI/CachingHelpers.cs @@ -36,19 +36,41 @@ public static string GetCacheKey(ReadOnlySpan values, JsonSerializerOpt // invalidating any existing cache entries that may exist in whatever IDistributedCache was in use. #if NET - IncrementalHashStream? stream = IncrementalHashStream.ThreadStaticInstance ?? new(); - IncrementalHashStream.ThreadStaticInstance = null; + IncrementalHashStream? stream = IncrementalHashStream.ThreadStaticInstance; + if (stream is not null) + { + // We need to ensure that the value in ThreadStaticInstance is always ready to use. + // If we start using an instance, write to it, and then fail, we will have left it + // in an inconsistent state. So, when renting it, we null it out, and we only put + // it back upon successful completion after resetting it. + IncrementalHashStream.ThreadStaticInstance = null; + } + else + { + stream = new(); + } - foreach (object? value in values) + string result; + try { - JsonSerializer.Serialize(stream, value, serializerOptions.GetTypeInfo(typeof(object))); + foreach (object? value in values) + { + JsonSerializer.Serialize(stream, value, serializerOptions.GetTypeInfo(typeof(object))); + } + + Span hashData = stackalloc byte[SHA256.HashSizeInBytes]; + stream.GetHashAndReset(hashData); + + result = Convert.ToHexString(hashData); + } + catch + { + stream.Dispose(); + throw; } - Span hashData = stackalloc byte[SHA256.HashSizeInBytes]; - stream.GetHashAndReset(hashData); IncrementalHashStream.ThreadStaticInstance = stream; - - return Convert.ToHexString(hashData); + return result; #else MemoryStream stream = new(); foreach (object? value in values) @@ -57,7 +79,6 @@ public static string GetCacheKey(ReadOnlySpan values, JsonSerializerOpt } using var sha256 = SHA256.Create(); - stream.Position = 0; var hashData = sha256.ComputeHash(stream.GetBuffer(), 0, (int)stream.Length); var chars = new char[hashData.Length * 2];