fix(ui/security): Enforce idempotent AI fetching, secure auth handler, and memory leak guards #45
@@ -31,7 +31,7 @@ public class KnowledgeService : IKnowledgeService
|
||||
private readonly Tokenizer _tokenizer;
|
||||
private readonly ILogger<KnowledgeService> _logger;
|
||||
private const string PromptVersion = "1.3";
|
||||
private static readonly ConcurrentDictionary<string, Task<Result<KnowledgePacket>>> _activeRequests = new();
|
||||
private static readonly ConcurrentDictionary<string, Lazy<Task<Result<KnowledgePacket>>>> _activeRequests = new();
|
||||
|
||||
public KnowledgeService(
|
||||
IChatClient chatClient,
|
||||
@@ -100,10 +100,38 @@ public class KnowledgeService : IKnowledgeService
|
||||
|
||||
// Deduplicate concurrent active requests for the exact same hash
|
||||
var requestKey = $"{tenantId}:{hash}:{traceType}";
|
||||
var task = _activeRequests.GetOrAdd(requestKey, _ =>
|
||||
ExecuteAiRequestAndCacheAsync(normalizedText, tenantId, systemPrompt, traceType, ebookId, hash));
|
||||
|
||||
var lazyTask = _activeRequests.GetOrAdd(requestKey, k =>
|
||||
new Lazy<Task<Result<KnowledgePacket>>>(
|
||||
() => ExecuteAiRequestAndCacheAsync(normalizedText, tenantId, systemPrompt, traceType, ebookId, hash),
|
||||
System.Threading.LazyThreadSafetyMode.ExecutionAndPublication
|
||||
));
|
||||
|
||||
return await task;
|
||||
try
|
||||
{
|
||||
var result = await lazyTask.Value;
|
||||
|
||||
// If the AI call returned a failure, remove it from the active dictionary
|
||||
// so subsequent retries have a chance to request the AI again.
|
||||
if (result.IsFailed)
|
||||
{
|
||||
_activeRequests.TryRemove(requestKey, out _);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Evict from active dictionary on hard exceptions to ensure system resiliency
|
||||
_activeRequests.TryRemove(requestKey, out _);
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Once a task successfully finishes and persists to the Persistent Database Cache,
|
||||
// we evict it from RAM (_activeRequests) since future hits will leverage the DB cache.
|
||||
_activeRequests.TryRemove(requestKey, out _);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Result<KnowledgePacket>> ExecuteAiRequestAndCacheAsync(
|
||||
|
||||
Reference in New Issue
Block a user