feat: parallel async processing and compact output mode

Major performance improvements:
- Parallel search execution across all queries
- Parallel article fetching with 10 concurrent limit
- Parallel embeddings with rate limiting (4 concurrent)
- Polly integration for retry resilience

New features:
- Add -v/--verbose flag for detailed output
- Compact single-line status mode with braille spinner
- StatusReporter service for unified output handling
- Query generation and errors hidden in compact mode
- ANSI escape codes for clean line updates

New files:
- Services/RateLimiter.cs - Semaphore-based concurrency control
- Services/StatusReporter.cs - Verbose/compact output handler
- Models/ParallelOptions.cs - Parallel processing configuration

All changes maintain Native AOT compatibility.
This commit is contained in:
2026-03-18 22:16:28 +01:00
parent 9d4bec7a17
commit b28d8998f7
9 changed files with 579 additions and 109 deletions

42
Services/RateLimiter.cs Normal file
View File

@@ -0,0 +1,42 @@
namespace OpenQuery.Services;
public sealed class RateLimiter : IAsyncDisposable
{
private readonly SemaphoreSlim _semaphore;
public RateLimiter(int maxConcurrentRequests)
{
_semaphore = new SemaphoreSlim(maxConcurrentRequests, maxConcurrentRequests);
}
public async Task<T> ExecuteAsync<T>(Func<Task<T>> action, CancellationToken cancellationToken = default)
{
await _semaphore.WaitAsync(cancellationToken);
try
{
return await action();
}
finally
{
_semaphore.Release();
}
}
public async Task ExecuteAsync(Func<Task> action, CancellationToken cancellationToken = default)
{
await _semaphore.WaitAsync(cancellationToken);
try
{
await action();
}
finally
{
_semaphore.Release();
}
}
public async ValueTask DisposeAsync()
{
_semaphore.Dispose();
}
}