using TarninaHub.Application.Matchmaking; namespace TarninaHub.Infrastructure.Llm; /// /// In-memory sliding-window request limiter (per instance) for LLM cost control. /// public sealed class InMemoryLlmRequestLimiter : ILlmRequestLimiter { private readonly int _maxPerWindow; private readonly TimeSpan _window; private readonly Queue _timestamps = new(); private readonly Lock _gate = new(); public InMemoryLlmRequestLimiter(int maxRequestsPerMinute, TimeSpan? window = null) { _maxPerWindow = Math.Max(1, maxRequestsPerMinute); _window = window ?? TimeSpan.FromMinutes(1); } public bool TryAcquire() { var now = DateTimeOffset.UtcNow; lock (_gate) { while (_timestamps.Count > 0 && now - _timestamps.Peek() > _window) { _timestamps.Dequeue(); } if (_timestamps.Count >= _maxPerWindow) { return false; } _timestamps.Enqueue(now); return true; } } }