IConcurrencyLimiter

Gates direct runs per train, per principal and globally. ITrainExecutionService.RunAsync acquires a permit after authorizing the caller and reading the input, and releases it when the run ends. Queued work does not pass through it. You configure it through the mediator builder rather than calling it; see Concurrency Limiting.

Signature

namespace Trax.Mediator.Services.ConcurrencyLimiter;
 
public interface IConcurrencyLimiter
{
    Task<IDisposable> AcquireAsync(string trainFullName, CancellationToken ct);
}
ParameterTypeDescription
trainFullNamestringThe train interface's FullName, the canonical train name
ctCancellationTokenCancels the wait; throws OperationCanceledException without taking a slot

Returns: a permit. Disposing it releases every slot it holds; disposing it twice is safe.

Behavior

  • Waits asynchronously while a limit is reached. It never rejects.
  • Takes the per-train, per-principal and global limits in that order, so two runs cannot deadlock on each other's slots.
  • The principal is whatever ICurrentPrincipalProvider returns at the time of the call.
  • A limit that is not configured is skipped.

AddMediator registers the default ConcurrencyLimiter as a singleton, built from MediatorConfiguration and the [TraxConcurrencyLimit] attributes discovery found. Replace it only to change how limits are enforced, for example to share them across processes; register yours after AddMediator.

Package

dotnet add package Trax.Mediator