Пример #1
0
        private static void MonitorProcessingTaskPrematureCompletion(Task processingTask, ISequence sequence)
        {
            if (sequence.ParentSequence != null)
            {
                return;
            }

            Task.Run(
                async() =>
            {
                try
                {
                    await processingTask.ConfigureAwait(false);

                    // Abort only parent sequences and don't consider the enumeration as aborted if the
                    // sequence is actually complete
                    if (sequence.ParentSequence != null || sequence.IsComplete)
                    {
                        return;
                    }

                    // Call AbortAsync to abort the uncompleted sequence, to avoid unreleased locks.
                    // The reason behind this call here may be counterintuitive but with
                    // SequenceAbortReason.EnumerationAborted a commit is in fact performed.
                    await sequence.AbortAsync(SequenceAbortReason.EnumerationAborted)
                    .ConfigureAwait(false);
                }
                catch (Exception exception)
                {
                    if (!sequence.IsPending || sequence.ParentSequence != null)
                    {
                        return;
                    }

                    await sequence.AbortAsync(SequenceAbortReason.Error, exception)
                    .ConfigureAwait(false);
                }
                finally
                {
                    if (sequence is ISequenceImplementation sequenceImplementation &&
                        sequenceImplementation.ShouldCreateNewActivity)
                    {
                        sequenceImplementation.Activity?.Stop();
                    }
                }
            });
        }
Пример #2
0
        private async Task <Task> PublishStreamProviderAsync(ISequence sequence, ConsumerPipelineContext context)
        {
            _logger.LogTraceWithMessageInfo(
                IntegrationEventIds.LowLevelTracing,
                $"Publishing {sequence.GetType().Name} '{sequence.SequenceId}'...",
                context);

            var publisher = context.ServiceProvider.GetRequiredService <IStreamPublisher>();

            var processingTasks = await publisher.PublishAsync(sequence.StreamProvider).ConfigureAwait(false);

            if (processingTasks.Count == 0)
            {
                _logger.LogTraceWithMessageInfo(
                    IntegrationEventIds.LowLevelTracing,
                    $"No subscribers for {sequence.GetType().Name} '{sequence.SequenceId}'.",
                    context);
                return(Task.CompletedTask);
            }

            return(Task.Run(
                       async() =>
            {
                try
                {
                    if (processingTasks.Count == 1)
                    {
                        await processingTasks.First().ConfigureAwait(false);
                        return;
                    }

                    using var cancellationTokenSource = new CancellationTokenSource();
                    var tasks = processingTasks.Select(task => task.CancelOnExceptionAsync(cancellationTokenSource))
                                .ToList();

                    await Task.WhenAny(tasks).ConfigureAwait(false);

                    if (!sequence.IsComplete && tasks.All(task => !task.IsFaulted))
                    {
                        // Call AbortAsync to abort the uncompleted sequence, to avoid unreleased locks.
                        // The reason behind this call here may be counterintuitive but with
                        // SequenceAbortReason.EnumerationAborted a commit is in fact performed.
                        await sequence.AbortAsync(SequenceAbortReason.EnumerationAborted).ConfigureAwait(false);
                    }

                    await Task.WhenAll(processingTasks).ConfigureAwait(false);
                }
                catch (Exception exception)
                {
                    await sequence.AbortAsync(SequenceAbortReason.Error, exception).ConfigureAwait(false);
                    sequence.Dispose();
                }
                finally
                {
                    _logger.LogTraceWithMessageInfo(
                        IntegrationEventIds.LowLevelTracing,
                        $"{sequence.GetType().Name} '{sequence.SequenceId}' processing completed.",
                        context);
                }
            }));
        }