perf: use stable sha256 cache keys for summarizer requests

This commit is contained in:
cesnimda
2026-03-22 14:01:55 +01:00
parent dfc8521ae3
commit 4ccfd6d055
3 changed files with 36 additions and 1 deletions
@@ -1,5 +1,6 @@
using System.Reflection;
using JobTrackerApi.Controllers;
using JobTrackerApi.Services;
using Xunit;
namespace JobTrackerApi.Tests;
@@ -20,4 +21,12 @@ public sealed class AttachmentsControllerTests
Assert.Contains(".png", values);
Assert.DoesNotContain(".exe", values);
}
[Fact]
public void Max_file_size_limit_is_10_mb()
{
var field = typeof(AttachmentsController).GetField("MaxFileSizeBytes", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(field);
Assert.Equal(10 * 1024 * 1024, (long)field!.GetValue(null)!);
}
}
@@ -1,5 +1,6 @@
using System.Reflection;
using JobTrackerApi.Controllers;
using JobTrackerApi.Services;
using Xunit;
namespace JobTrackerApi.Tests;
@@ -19,4 +20,19 @@ public sealed class OwnershipGuardTests
var method = typeof(CorrespondenceController).GetMethod("FindOwnedMessageAsync", BindingFlags.NonPublic | BindingFlags.Instance);
Assert.NotNull(method);
}
[Fact]
public void Summarizer_service_uses_sha256_cache_key_builder()
{
var method = typeof(SummarizerService).GetMethod("BuildCacheKey", BindingFlags.NonPublic | BindingFlags.Static);
Assert.NotNull(method);
var first = (string)method!.Invoke(null, new object[] { "example text", 150, 30 })!;
var second = (string)method.Invoke(null, new object[] { "example text", 150, 30 })!;
var different = (string)method.Invoke(null, new object[] { "different text", 150, 30 })!;
Assert.Equal(first, second);
Assert.StartsWith("summ:", first);
Assert.NotEqual(first, different);
}
}
+11 -1
View File
@@ -1,6 +1,7 @@
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
@@ -63,11 +64,20 @@ namespace JobTrackerApi.Services
_cache = cache;
}
private static string BuildCacheKey(string text, int maxLength, int minLength)
{
var payload = $"{text}\n::{maxLength}:{minLength}";
var hash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(payload))).ToLowerInvariant();
return $"summ:{hash}";
}
public async Task<string?> SummarizeAsync(string text, int maxLength = 150, int minLength = 30)
{
if (string.IsNullOrWhiteSpace(text)) return null;
var key = $"summ:{text.GetHashCode()}:{maxLength}:{minLength}";
// Use a deterministic content hash instead of string.GetHashCode() so cache keys
// are collision-resistant and stable across process restarts.
var key = BuildCacheKey(text, maxLength, minLength);
Interlocked.Increment(ref _requests);
if (_cache.TryGetValue<string>(key, out var cached))