예제 #1
0
        Task <T> Execute(Task <T> task, Func <T, Task <T> > continuationTask, ExecuteOptions options)
        {
            if (task.IsCompleted && options.HasFlag(ExecuteOptions.RunSynchronously))
            {
                if (task.IsFaulted)
                {
                    return(TaskUtil.Faulted <T>(task.Exception.InnerExceptions));
                }

                if (task.IsCanceled || _cancellationToken.IsCancellationRequested)
                {
                    return(TaskUtil.Canceled <T>());
                }

                if (task.Status == TaskStatus.RanToCompletion)
                {
                    try
                    {
                        return(continuationTask(task.Result));
                    }
                    catch (Exception ex)
                    {
                        return(TaskUtil.Faulted <T>(ex));
                    }
                }
            }

            return(ExecuteAsync(task, continuationTask, options));
        }
예제 #2
0
        protected Task ExceptionHandler(ExceptionReceivedEventArgs args)
        {
            int  activeDispatchCount = _messageReceiver.ActiveDispatchCount;
            bool requiresRecycle     = true;

            if (args.Exception is MessageLockLostException)
            {
                requiresRecycle = false;
            }
            else if (args.Exception is ServiceBusException sbException)
            {
                requiresRecycle = !sbException.IsTransient;
            }

            if (!(args.Exception is OperationCanceledException))
            {
                LogContext.Error?.Log(args.Exception,
                                      "Exception on Receiver {InputAddress} during {Action} ActiveDispatchCount({activeDispatch}) ErrorRequiresRecycle({requiresRecycle})",
                                      _context.InputAddress, args.ExceptionReceivedContext.Action, activeDispatchCount, requiresRecycle);
            }

            if (activeDispatchCount == 0 && requiresRecycle)
            {
                LogContext.Debug?.Log("Receiver shutdown completed: {InputAddress}", _context.InputAddress);

                _deliveryComplete.TrySetResult(true);

                SetCompleted(TaskUtil.Faulted <bool>(args.Exception));
            }

            return(Task.CompletedTask);
        }
예제 #3
0
        Task <T> Compensate(Task <T> task, Func <Task <T>, Task <T> > compensationTask)
        {
            if (task.IsCompleted)
            {
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    var tcs = new TaskCompletionSource <T>();
                    tcs.TrySetFromTask(task);
                    return(tcs.Task);
                }

                try
                {
                    Task <T> resultTask = compensationTask(task);
                    if (resultTask == null)
                    {
                        throw new InvalidOperationException("Sure could use a Task here buddy");
                    }

                    return(resultTask);
                }
                catch (Exception ex)
                {
                    return(TaskUtil.Faulted <T>(ex));
                }
            }

            return(CompensateAsync(task, compensationTask));
        }
예제 #4
0
        public static Task <Guid?> ShouldContainSaga <TSaga>(this ISagaRepository <TSaga> repository, Guid sagaId, TimeSpan timeout)
            where TSaga : class, ISaga
        {
            if (repository is IQuerySagaRepository <TSaga> querySagaRepository)
            {
                return(querySagaRepository.ShouldContainSaga(sagaId, timeout));
            }

            return(TaskUtil.Faulted <Guid?>(new ArgumentException("Does not support IQuerySagaRepository", nameof(repository))));
        }
예제 #5
0
        public Task <TSaga> Load(Guid correlationId)
        {
            return(_repositoryContextFactory.Execute(context =>
            {
                if (context is MongoDbSagaRepositoryContext <TSaga> mongoDbSagaRepositoryContext)
                {
                    return mongoDbSagaRepositoryContext.Load(correlationId);
                }

                return TaskUtil.Faulted <TSaga>(new NotSupportedException($"{nameof(Load)} is not supported for {TypeMetadataCache<TSaga>.ShortName}"));
            }));
        }
예제 #6
0
        async Task HandleError(ProcessErrorEventArgs eventArgs)
        {
            LogContext.SetCurrentIfNull(_context.LogContext);

            var activeDispatchCount = _dispatcher.ActiveDispatchCount;

            if (activeDispatchCount == 0)
            {
                LogContext.Debug?.Log("Receiver shutdown completed: {InputAddress}, PartitionId: {PartitionId}", _context.InputAddress, eventArgs.PartitionId);

                _deliveryComplete.TrySetResult(true);

                SetCompleted(TaskUtil.Faulted <bool>(eventArgs.Exception));
            }
        }
예제 #7
0
        void HandleKafkaError(IConsumer <TKey, TValue> consumer, Error error)
        {
            if (_cancellationTokenSource.Token.IsCancellationRequested)
            {
                return;
            }
            var activeDispatchCount = _dispatcher.ActiveDispatchCount;

            LogContext.Error?.Log("Consumer error ({Code}): {Reason} on {Topic}", error.Code, error.Reason, _consumerContext.ReceiveSettings.Topic);
            if (activeDispatchCount == 0 || error.IsLocalError)
            {
                _cancellationTokenSource.Cancel();
                _deliveryComplete.TrySetResult(true);
                SetCompleted(TaskUtil.Faulted <bool>(new KafkaException(error)));
            }
        }
예제 #8
0
        protected void ExceptionHandler(object sender, ExceptionReceivedEventArgs args)
        {
            if (!(args.Exception is OperationCanceledException))
            {
                LogContext.Error?.Log(args.Exception, "Exception on Receiver {InputAddress} during {Action}", _context.InputAddress, args.Action);
            }

            if (_tracker.ActiveDeliveryCount == 0)
            {
                LogContext.Debug?.Log("Receiver shutdown completed: {InputAddress}", _context.InputAddress);

                _deliveryComplete.TrySetResult(true);

                SetCompleted(TaskUtil.Faulted <bool>(args.Exception));
            }
        }
예제 #9
0
        protected Task ExceptionHandler(ExceptionReceivedEventArgs args)
        {
            if (!(args.Exception is OperationCanceledException))
            {
                LogContext.Error?.Log(args.Exception, "Exception on Receiver {InputAddress} during {Action}", _context.InputAddress,
                                      args.ExceptionReceivedContext.Action);
            }

            if (_messageReceiver.ActiveDispatchCount == 0)
            {
                LogContext.Debug?.Log("Receiver shutdown completed: {InputAddress}", _context.InputAddress);

                _deliveryComplete.TrySetResult(true);

                SetCompleted(TaskUtil.Faulted <bool>(args.Exception));
            }

            return(Task.CompletedTask);
        }
예제 #10
0
        protected void ExceptionHandler(object sender, ExceptionReceivedEventArgs args)
        {
            if (!(args.Exception is OperationCanceledException))
            {
                if (_log.IsErrorEnabled)
                {
                    _log.Error($"Exception received on receiver: {_context.InputAddress} during {args.Action}", args.Exception);
                }
            }

            if (_tracker.ActiveDeliveryCount == 0)
            {
                if (_log.IsDebugEnabled)
                {
                    _log.DebugFormat("Receiver shutdown completed: {0}", _context.InputAddress);
                }

                _deliveryComplete.TrySetResult(true);

                SetCompleted(TaskUtil.Faulted <bool>(args.Exception));
            }
        }
예제 #11
0
        async Task Consume()
        {
            var prefetchCount = Math.Max(1000, _consumerContext.ReceiveSettings.CheckpointMessageCount / 10);
            var executor      = new ChannelExecutor(prefetchCount, _consumerContext.ReceiveSettings.ConcurrencyLimit);

            await _consumerContext.Subscribe().ConfigureAwait(false);

            SetReady();

            try
            {
                while (!_cancellationTokenSource.IsCancellationRequested)
                {
                    ConsumeResult <TKey, TValue> consumeResult = await _consumerContext.Consume(_cancellationTokenSource.Token).ConfigureAwait(false);

                    await executor.Push(() => Handle(consumeResult), Stopping).ConfigureAwait(false);
                }

                SetCompleted(TaskUtil.Completed);
            }
            catch (OperationCanceledException exception) when(exception.CancellationToken == Stopping ||
                                                              exception.CancellationToken == _cancellationTokenSource.Token)
            {
                SetCompleted(TaskUtil.Completed);
            }
            catch (Exception exception)
            {
                LogContext.Error?.Log(exception, "Consume Loop faulted");

                SetCompleted(TaskUtil.Faulted <bool>(exception));
            }
            finally
            {
                await executor.DisposeAsync().ConfigureAwait(false);
            }
        }
예제 #12
0
 Task ModelContext.BasicAck(ulong deliveryTag, bool multiple)
 {
     return(_model.IsClosed
         ? TaskUtil.Faulted <bool>(new InvalidOperationException($"The channel was closed: {_model.CloseReason} {_model.ChannelNumber}"))
         : _executor.Run(() => _model.BasicAck(deliveryTag, multiple), CancellationToken));
 }
예제 #13
0
 Composer <T> Composer <T> .Fault <TException>(TException exception)
 {
     _task = Execute(_task, payload => TaskUtil.Faulted <T>(exception), ExecuteOptions.None);
     return(this);
 }
예제 #14
0
 CompensationResult <T> Compensation <T> .Throw <TException>(TException exception)
 {
     return(new Result(TaskUtil.Faulted <T>(exception)));
 }