MarketAlly.AIPlugin.Extensions/MarketAlly.AIPlugin.Analysis/Infrastructure/AnalysisContext.cs

108 lines
3.3 KiB
C#
Executable File

using Microsoft.Extensions.Logging;
using System;
using System.Threading;
namespace MarketAlly.AIPlugin.Analysis.Infrastructure
{
/// <summary>
/// Context for analysis operations with resource management
/// </summary>
public class AnalysisContext : IDisposable
{
private readonly CancellationTokenSource _cancellationTokenSource = new();
private readonly SemaphoreSlim _concurrencySemaphore;
private readonly ILogger? _logger;
private bool _disposed = false;
/// <summary>
/// Cancellation token for the analysis operation
/// </summary>
public CancellationToken CancellationToken => _cancellationTokenSource.Token;
/// <summary>
/// Configuration for the analysis
/// </summary>
public AnalysisConfiguration Configuration { get; }
/// <summary>
/// Logger for the analysis context
/// </summary>
public ILogger? Logger => _logger;
/// <summary>
/// Semaphore for controlling concurrency
/// </summary>
public SemaphoreSlim ConcurrencySemaphore => _concurrencySemaphore;
public AnalysisContext(AnalysisConfiguration configuration, ILogger? logger = null)
{
Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
_logger = logger;
_concurrencySemaphore = new SemaphoreSlim(
configuration.MaxConcurrentAnalyses,
configuration.MaxConcurrentAnalyses);
}
/// <summary>
/// Creates a child context with the same configuration but separate cancellation
/// </summary>
public AnalysisContext CreateChildContext()
{
ThrowIfDisposed();
var childContext = new AnalysisContext(Configuration, _logger);
// Link the child's cancellation to the parent's
_cancellationTokenSource.Token.Register(() => childContext._cancellationTokenSource.Cancel());
return childContext;
}
/// <summary>
/// Cancels the analysis operation
/// </summary>
public void Cancel()
{
ThrowIfDisposed();
_cancellationTokenSource.Cancel();
}
/// <summary>
/// Waits for a concurrency slot to become available
/// </summary>
public async Task AcquireConcurrencySlotAsync()
{
ThrowIfDisposed();
await _concurrencySemaphore.WaitAsync(CancellationToken);
}
/// <summary>
/// Releases a concurrency slot
/// </summary>
public void ReleaseConcurrencySlot()
{
if (!_disposed)
{
_concurrencySemaphore.Release();
}
}
public void Dispose()
{
if (!_disposed)
{
_cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
_concurrencySemaphore?.Dispose();
_disposed = true;
}
}
private void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(AnalysisContext));
}
}
}
}