private Action <DeliveryReport <K, V> > BuildSendCallback <TResult>(TaskCompletionSource <TResult> completion, Action <DeliveryReport <K, V> > onSuccess) { return(report => { if (!report.Error.IsError) { onSuccess(report); } else { Log.Error(report.Error.Reason); var exception = new KafkaException(report.Error); switch (_decider(exception)) { case Directive.Stop: if (_stage.CloseProducerOnStop) { // TODO: address the missing Producer.Close() in the future Producer.Dispose(); } _failStageCallback(exception); break; default: completion.SetException(exception); break; } } if (AwaitingConfirmation.DecrementAndGet() == 0 && _inIsClosed) { _checkForCompletionCallback(); } }); }
public ProducerStageLogic(ProducerStage <K, V> stage, Attributes attributes) : base(stage.Shape) { _stage = stage; var supervisionStrategy = attributes.GetAttribute <ActorAttributes.SupervisionStrategy>(null); var decider = supervisionStrategy != null ? supervisionStrategy.Decider : Deciders.ResumingDecider; SetHandler(_stage.In, onPush: () => { var msg = Grab(_stage.In); var result = new TaskCompletionSource <DeliveryReport <K, V> >(); _producer.Produce(msg.TopicPartition, msg.Message, report => { if (!report.Error.HasError) { result.SetResult(report); } else { var exception = new KafkaException(report.Error); switch (decider(exception)) { case Directive.Stop: if (_stage.CloseProducerOnStop) { _producer.Dispose(); } FailStage(exception); break; default: result.SetException(exception); break; } } if (_awaitingConfirmation.DecrementAndGet() == 0 && _inIsClosed) { CheckForCompletion(); } }); _awaitingConfirmation.IncrementAndGet(); Push(_stage.Out, result.Task); }, onUpstreamFinish: () => { _inIsClosed = true; _completionState.SetResult(NotUsed.Instance); CheckForCompletion(); }, onUpstreamFailure: exception => { _inIsClosed = true; _completionState.SetException(exception); CheckForCompletion(); }); SetHandler(_stage.Out, onPull: () => { TryPull(_stage.In); }); }