public DefaultProducerStageLogic(IProducerStage <K, V, P, TIn, TOut> stage, Attributes attributes) : base(stage.Shape) { _stage = stage; var supervisionStrategy = attributes.GetAttribute <ActorAttributes.SupervisionStrategy>(null); _decider = supervisionStrategy != null ? supervisionStrategy.Decider : Deciders.StoppingDecider; _checkForCompletionCallback = GetAsyncCallback(CheckForCompletion); _failStageCallback = GetAsyncCallback <Exception>(FailStage); SetHandler(_stage.In, onPush: () => { var msg = Grab(_stage.In) as IEnvelope <K, V, P>; switch (msg) { case Message <K, V, P> message: { var result = new TaskCompletionSource <IResults <K, V, P> >(); AwaitingConfirmation.IncrementAndGet(); Producer.Produce(message.Record, BuildSendCallback(result, onSuccess: report => { result.SetResult(new Result <K, V, P>(report, message)); })); PostSend(msg); Push(stage.Out, result.Task as Task <TOut>); break; } case MultiMessage <K, V, P> multiMessage: { var tasks = multiMessage.Records.Select(record => { var result = new TaskCompletionSource <MultiResultPart <K, V> >(); AwaitingConfirmation.IncrementAndGet(); Producer.Produce(record, BuildSendCallback(result, report => { result.SetResult(new MultiResultPart <K, V>(report, record)); })); return(result.Task); }); PostSend(msg); var resultTask = Task.WhenAll(tasks).ContinueWith(t => new MultiResult <K, V, P>(t.Result.ToImmutableHashSet(), multiMessage.PassThrough) as IResults <K, V, P>); Push(stage.Out, resultTask as Task <TOut>); break; } case PassThroughMessage <K, V, P> passThroughMessage: { PostSend(msg); var resultTask = Task.FromResult(new PassThroughResult <K, V, P>(passThroughMessage.PassThrough) as IResults <K, V, P>); Push(stage.Out, resultTask as Task <TOut>); break; } } }, onUpstreamFinish: () => { _inIsClosed = true; _completionState.SetResult(NotUsed.Instance); _checkForCompletionCallback(); }, onUpstreamFailure: exception => { _inIsClosed = true; _completionState.SetException(exception); _checkForCompletionCallback(); }); SetHandler(_stage.Out, onPull: () => { TryPull(_stage.In); }); }
public DefaultProducerStageLogic(IProducerStage <K, V, P, TIn, TOut> stage, Attributes attributes) : base(stage.Shape) { _stage = stage; // TODO: Move this to the GraphStage.InitialAttribute when it is fixed (https://github.com/akkadotnet/akka.net/issues/5388) var supervisionStrategy = attributes.GetAttribute(new ActorAttributes.SupervisionStrategy(new DefaultProducerDecider <K, V>().Decide)); _decider = supervisionStrategy.Decider; SetHandler(_stage.In, onPush: () => { var msg = Grab(_stage.In) as IEnvelope <K, V, P>; switch (msg) { case Message <K, V, P> message: { var result = new TaskCompletionSource <IResults <K, V, P> >(); AwaitingConfirmation.IncrementAndGet(); try { var callback = BuildSendCallback( completion: result, onSuccess: report => { result.SetResult(new Result <K, V, P>(report, message)); }, onFailure: OnProduceFailure); Producer.Produce(message.Record, GetAsyncCallback(callback)); PostSend(msg); Push(stage.Out, result.Task as Task <TOut>); } catch (Exception exception) { OnProduceFailure(exception); } break; } case MultiMessage <K, V, P> multiMessage: { var tasks = multiMessage.Records.Select(record => { var result = new TaskCompletionSource <MultiResultPart <K, V> >(); AwaitingConfirmation.IncrementAndGet(); var callback = BuildSendCallback( completion: result, onSuccess: report => { result.SetResult(new MultiResultPart <K, V>(report, record)); }, onFailure: OnProduceFailure); try { Producer.Produce(record, GetAsyncCallback(callback)); return(result.Task); } catch (Exception exception) { OnProduceFailure(exception); return(null); } }).Where(t => t != null).ToArray(); if (tasks.Length > 0) { PostSend(msg); var resultTask = Task.WhenAll(tasks).ContinueWith(t => new MultiResult <K, V, P>(t.Result.ToImmutableHashSet(), multiMessage.PassThrough) as IResults <K, V, P>); Push(stage.Out, resultTask as Task <TOut>); } else { TryPull(_stage.In); } break; } case PassThroughMessage <K, V, P> passThroughMessage: { PostSend(msg); var resultTask = Task.FromResult(new PassThroughResult <K, V, P>(passThroughMessage.PassThrough) as IResults <K, V, P>); Push(stage.Out, resultTask as Task <TOut>); break; } } }, onUpstreamFinish: () => { _completionState.SetResult(NotUsed.Instance); CheckForCompletion(); }, onUpstreamFailure: exception => { _completionState.SetException(exception); CheckForCompletion(); }); SetHandler(_stage.Out, onPull: () => { TryPull(_stage.In); }); }