in src/DotPulsar/Extensions/StateHolderExtensions.cs [33:105]
public static async ValueTask<TState> OnStateChangeTo<TState>(
this IStateHolder<TState> stateHolder,
TState state,
TimeSpan delay,
CancellationToken cancellationToken = default) where TState : notnull
=> await stateHolder.State.OnStateChangeTo(state, delay, cancellationToken);
/// <summary>
/// Wait for the state to change from a specific state with a delay.
/// </summary>
/// <returns>
/// The current state.
/// </returns>
/// <remarks>
/// If the state change to a final state, then all awaiting tasks will complete.
/// </remarks>
public static async ValueTask<TState> OnStateChangeFrom<TState>(
this IStateHolder<TState> stateHolder,
TState state,
TimeSpan delay,
CancellationToken cancellationToken = default) where TState : notnull
=> await stateHolder.State.OnStateChangeFrom(state, delay, cancellationToken);
/// <summary>
/// Will invoke the onStateLeft callback when the state if left (with delay) and onStateReached when it's reached again.
/// </summary>
/// <returns>
/// ValueTask that will run as long as a final state is not entered.
/// </returns>
public static async ValueTask DelayedStateMonitor<TEntity, TState, TFaultContext>(
this TEntity stateHolder,
TState state,
TimeSpan delay,
Func<TEntity, TState, CancellationToken, ValueTask<TFaultContext>> onStateLeft,
Func<TEntity, TState, TFaultContext, CancellationToken, ValueTask> onStateReached,
CancellationToken cancellationToken = default) where TEntity : IStateHolder<TState> where TState : notnull where TFaultContext : class
{
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
var currentState = await stateHolder.OnStateChangeFrom(state, delay, cancellationToken).ConfigureAwait(false);
TFaultContext? faultContext = null;
try
{
faultContext = await onStateLeft(stateHolder, currentState, cancellationToken).ConfigureAwait(false);
}
catch
{
// Ignore
}
if (stateHolder.State.IsFinalState(currentState))
return;
currentState = await stateHolder.State.OnStateChangeTo(state, cancellationToken).ConfigureAwait(false);
if (stateHolder.State.IsFinalState(currentState))
return;
try
{
if (faultContext is not null)
await onStateReached(stateHolder, currentState, faultContext, cancellationToken).ConfigureAwait(false);
}
catch
{
// Ignore
}
}
}