public ISagaQueryScopeContext <TSaga, T> GetQueryScope <T>(SagaQueryConsumeContext <TSaga, T> context)
            where T : class
        {
            if (context.TryGetPayload <IKernel>(out var kernel))
            {
                kernel.UpdateScope(context);

                return(new ExistingSagaQueryScopeContext <TSaga, T>(context));
            }

            var scope = _kernel.CreateNewOrUseExistingMessageScope(context);

            try
            {
                var proxy = new SagaQueryConsumeContextScope <TSaga, T>(context, context.Query, _kernel);

                foreach (Action <ConsumeContext> scopeAction in _scopeActions)
                {
                    scopeAction(proxy);
                }

                return(new CreatedSagaQueryScopeContext <IDisposable, TSaga, T>(scope, proxy));
            }
            catch
            {
                scope.Dispose();
                throw;
            }
        }
Example #2
0
        async Task IFilter <ConsumeContext <TMessage> > .Send(ConsumeContext <TMessage> context, IPipe <ConsumeContext <TMessage> > next)
        {
            Stopwatch timer = Stopwatch.StartNew();

            var activity = LogContext.IfEnabled(OperationName.Saga.SendQuery)?.StartActivity(new
            {
                SagaType    = TypeMetadataCache <TSaga> .ShortName,
                MessageType = TypeMetadataCache <TMessage> .ShortName
            });

            try
            {
                ISagaQuery <TSaga> query = _queryFactory.CreateQuery(context);

                SagaQueryConsumeContext <TSaga, TMessage> queryContext = new SagaQueryConsumeContextScope <TSaga, TMessage>(context, query);

                await Task.Yield();

                await _sagaRepository.SendQuery(queryContext, _policy, _messagePipe).ConfigureAwait(false);

                await next.Send(context).ConfigureAwait(false);

                await context.NotifyConsumed(timer.Elapsed, TypeMetadataCache <TSaga> .ShortName).ConfigureAwait(false);
            }
            catch (OperationCanceledException exception)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TSaga> .ShortName, exception).ConfigureAwait(false);

                if (exception.CancellationToken == context.CancellationToken)
                {
                    throw;
                }

                throw new ConsumerCanceledException($"The operation was cancelled by the consumer: {TypeMetadataCache<TSaga>.ShortName}");
            }
            catch (Exception ex)
            {
                await context.NotifyFaulted(timer.Elapsed, TypeMetadataCache <TSaga> .ShortName, ex).ConfigureAwait(false);

                throw;
            }
            finally
            {
                activity?.Stop();
            }
        }
        ISagaQueryScopeContext <TSaga, T> ISagaScopeProvider <TSaga> .GetQueryScope <T>(SagaQueryConsumeContext <TSaga, T> context)
        {
            if (context.TryGetPayload <IUnityContainer>(out var existingScope))
            {
                return(new ExistingSagaQueryScopeContext <TSaga, T>(context));
            }

            var scope = _container.CreateChildContainer();

            try
            {
                var proxy = new SagaQueryConsumeContextScope <TSaga, T>(context, context.Query, scope);

                return(new CreatedSagaQueryScopeContext <IUnityContainer, TSaga, T>(scope, proxy));
            }
            catch
            {
                scope.Dispose();

                throw;
            }
        }