/// <summary> /// Adds a context to the supervisor as an agent, which can be stopped by the supervisor. /// </summary> /// <param name="supervisor">The supervisor</param> /// <typeparam name="T">The context type</typeparam> /// <returns>A context handle</returns> public static IAsyncPipeContextAgent <T> AddAsyncContext <T>(this ISupervisor supervisor) where T : class, PipeContext { if (supervisor == null) { throw new ArgumentNullException(nameof(supervisor)); } IAsyncPipeContextAgent <T> contextAgent = new AsyncPipeContextAgent <T>(); supervisor.Add(contextAgent); return(contextAgent); }
async Task <TContext> CreateJoinContext(IAsyncPipeContextAgent <TContext> asyncContext, CancellationToken cancellationToken) { IAsyncPipeContextAgent <TLeft> leftAgent = new AsyncPipeContextAgent <TLeft>(); IAsyncPipeContextAgent <TRight> rightAgent = new AsyncPipeContextAgent <TRight>(); var leftPipe = new AsyncPipeContextPipe <TLeft>(leftAgent, _leftPipe); var leftTask = _leftSource.Send(leftPipe, cancellationToken); var rightPipe = new AsyncPipeContextPipe <TRight>(rightAgent, _rightPipe); var rightTask = _rightSource.Send(rightPipe, cancellationToken); async Task Join() { try { var leftAny = await Task.WhenAny(leftAgent.Context, leftTask).ConfigureAwait(false); if (leftAny == leftTask) { await leftTask.ConfigureAwait(false); } var rightAny = await Task.WhenAny(rightAgent.Context, rightTask).ConfigureAwait(false); if (rightAny == rightTask) { await rightTask.ConfigureAwait(false); } var leftContext = await leftAgent.Context.ConfigureAwait(false); var rightContext = await rightAgent.Context.ConfigureAwait(false); var clientContext = CreateClientContext(leftContext, rightContext); clientContext.GetOrAddPayload(() => rightContext); clientContext.GetOrAddPayload(() => leftContext); await asyncContext.Created(clientContext).ConfigureAwait(false); await asyncContext.Completed.ConfigureAwait(false); } catch (OperationCanceledException) { await asyncContext.CreateCanceled().ConfigureAwait(false); } catch (Exception exception) { await asyncContext.CreateFaulted(exception).ConfigureAwait(false); } finally { await Task.WhenAll(leftAgent.Stop("Complete", cancellationToken), rightAgent.Stop("Complete", cancellationToken)).ConfigureAwait(false); } try { await Task.WhenAll(leftTask, rightTask).ConfigureAwait(false); } catch (Exception exception) { LogContext.Warning?.Log(exception, "Join faulted"); } } await Task.WhenAny(asyncContext.Context, Join()).ConfigureAwait(false); return(await asyncContext.Context.ConfigureAwait(false)); }