コード例 #1
0
        async Task SendToInstance <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, SagaInstance <TSaga> saga,
                                      IPipe <SagaConsumeContext <TSaga, T> > next)
            where T : class
        {
            await saga.MarkInUse(context.CancellationToken).ConfigureAwait(false);

            try
            {
                if (saga.IsRemoved)
                {
                    return;
                }

                SagaConsumeContext <TSaga, T> sagaConsumeContext = new InMemorySagaConsumeContext <TSaga, T>(context, saga.Instance,
                                                                                                             () => Remove(saga, context.CancellationToken));

                sagaConsumeContext.LogUsed();

                await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false);
            }
            finally
            {
                saga.Release();
            }
        }
コード例 #2
0
        public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
            where T : class
        {
            try
            {
                List <TSaga> sagaInstances = await _collection.Find(context.Query.FilterExpression).ToListAsync().ConfigureAwait(false);

                if (!sagaInstances.Any())
                {
                    var missingPipe = new MissingPipe <TSaga, T>(_collection, next, _mongoDbSagaConsumeContextFactory);

                    await policy.Missing(context, missingPipe).ConfigureAwait(false);
                }
                else
                {
                    foreach (var instance in sagaInstances)
                    {
                        await SendToInstance(context, policy, next, instance).ConfigureAwait(false);
                    }
                }
            }
            catch (SagaException sex)
            {
                context.LogFault(sex);

                throw;
            }
            catch (Exception ex)
            {
                context.LogFault(ex);

                throw new SagaException(ex.Message, typeof(TSaga), typeof(T), Guid.Empty, ex);
            }
        }
コード例 #3
0
        async Task SendToInstance <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, SagaInstance <TSaga> saga,
                                      IPipe <SagaConsumeContext <TSaga, T> > next)
            where T : class
        {
            await saga.MarkInUse(context.CancellationToken).ConfigureAwait(false);

            try
            {
                if (saga.IsRemoved)
                {
                    return;
                }

                if (_log.IsDebugEnabled)
                {
                    _log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName, saga.Instance.CorrelationId, TypeMetadataCache <T> .ShortName);
                }

                SagaConsumeContext <TSaga, T> sagaConsumeContext = new InMemorySagaConsumeContext <TSaga, T>(context, saga.Instance,
                                                                                                             () => Remove(saga, context.CancellationToken));

                await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false);
            }
            finally
            {
                saga.Release();
            }
        }
コード例 #4
0
        public ISagaQueryScopeContext <TSaga, T> GetQueryScope <T>(SagaQueryConsumeContext <TSaga, T> context) where T : class
        {
            if (context.TryGetPayload <IKernel>(out _))
            {
                return(new ExistingSagaQueryScopeContext <TSaga, T>(context));
            }

            var scope = _container.BeginScope();

            _container.Register(Component.For <ConsumeContext, ConsumeContext <T> >().Instance(context));

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

                var consumerContainer = _container;
                proxy.GetOrAddPayload(() => consumerContainer);
                foreach (Action <ConsumeContext> scopeAction in _scopeActions)
                {
                    scopeAction(proxy);
                }

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

                throw;
            }
        }
コード例 #5
0
 public static void LogFault <TSaga, TMessage>(this SagaQueryConsumeContext <TSaga, TMessage> context, Exception exception, Guid?correlationId = default)
     where TSaga : class, ISaga
     where TMessage : class
 {
     LogContext.Error?.Log(exception, "SAGA:{SagaType}:{CorrelationId} Fault {MessageType}", TypeMetadataCache <TSaga> .ShortName, correlationId,
                           TypeMetadataCache <TMessage> .ShortName);
 }
コード例 #6
0
 async Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
 {
     using (_container.RequireScope())
     {
         await _repository.SendQuery(context, policy, next).ConfigureAwait(false);
     }
 }
コード例 #7
0
        private static async Task SendToInstance <T>(SagaQueryConsumeContext <TSaga, T> context,
                                                     ISagaPolicy <TSaga, T> policy, TSaga instance,
                                                     IPipe <SagaConsumeContext <TSaga, T> > next, IAsyncDocumentSession session)
            where T : class
        {
            try
            {
                if (_log.IsDebugEnabled)
                {
                    _log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName,
                                     instance.CorrelationId,
                                     TypeMetadataCache <T> .ShortName);
                }
                var sagaConsumeContext = new RavenDbSagaConsumeContext <TSaga, T>(session, context, instance);

                await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false);
            }
            catch (SagaException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex);
            }
        }
コード例 #8
0
        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();

            try
            {
                _kernel.UpdateScope(context);

                var proxy = new SagaQueryConsumeContextProxy <TSaga, T>(context, new PayloadCacheScope(context), context.Query);
                proxy.UpdatePayload(_kernel);

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

                return(new CreatedSagaQueryScopeContext <IDisposable, TSaga, T>(scope, proxy));
            }
            catch
            {
                scope.Dispose();
                throw;
            }
        }
コード例 #9
0
        public ISagaQueryScopeContext <TSaga, T> GetQueryScope <T>(SagaQueryConsumeContext <TSaga, T> context) where T : class
        {
            if (context.TryGetPayload <IUnityContainer>(out var existingScope))
            {
                return(new ExistingSagaQueryScopeContext <TSaga, T>(context));
            }

            var scope = _container.CreateChildContainer();

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

                var sagaScope = scope;
                proxy.GetOrAddPayload(() => sagaScope);

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

                throw;
            }
        }
コード例 #10
0
        public ISagaQueryScopeContext <TSaga, T> GetQueryScope <T>(SagaQueryConsumeContext <TSaga, T> context)
            where T : class
        {
            if (context.TryGetPayload <INestedContainer>(out var existingNestedContainer))
            {
                existingNestedContainer.Inject <ConsumeContext>(context);

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

            var nestedContainer = _container.GetNestedContainer(context);

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

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

                return(new CreatedSagaQueryScopeContext <INestedContainer, TSaga, T>(nestedContainer, proxy));
            }
            catch
            {
                nestedContainer.Dispose();
                throw;
            }
        }
コード例 #11
0
 public Task SendQuery <T>(
     SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
     IPipe <SagaConsumeContext <TSaga, T> > next
     ) where T : class
 {
     throw new NotImplementedByDesignException("Redis saga repository does not support queries");
 }
コード例 #12
0
        public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
            where T : class
        {
            using (var session = _sessionFactory.OpenSession())
                using (var transaction = session.BeginTransaction())
                {
                    try
                    {
                        IList <TSaga> instances = await session.QueryOver <TSaga>()
                                                  .Where(context.Query.FilterExpression)
                                                  .ListAsync <TSaga>()
                                                  .ConfigureAwait(false);

                        if (instances.Count == 0)
                        {
                            var missingSagaPipe = new MissingPipe <T>(session, next);
                            await policy.Missing(context, missingSagaPipe).ConfigureAwait(false);
                        }
                        else
                        {
                            await Task.WhenAll(instances.Select(instance => SendToInstance(context, policy, instance, next, session))).ConfigureAwait(false);
                        }

                        // TODO partial failure should not affect them all

                        if (transaction.IsActive)
                        {
                            await transaction.CommitAsync().ConfigureAwait(false);
                        }
                    }
                    catch (SagaException sex)
                    {
                        if (_log.IsErrorEnabled)
                        {
                            _log.Error($"SAGA:{TypeMetadataCache<TSaga>.ShortName} Exception {TypeMetadataCache<T>.ShortName}", sex);
                        }

                        if (transaction.IsActive)
                        {
                            await transaction.RollbackAsync().ConfigureAwait(false);
                        }

                        throw;
                    }
                    catch (Exception ex)
                    {
                        if (_log.IsErrorEnabled)
                        {
                            _log.Error($"SAGA:{TypeMetadataCache<TSaga>.ShortName} Exception {TypeMetadataCache<T>.ShortName}", ex);
                        }

                        if (transaction.IsActive)
                        {
                            await transaction.RollbackAsync().ConfigureAwait(false);
                        }

                        throw new SagaException(ex.Message, typeof(TSaga), typeof(T), Guid.Empty, ex);
                    }
                }
        }
コード例 #13
0
        public ISagaQueryScopeContext <TSaga, T> GetQueryScope <T>(SagaQueryConsumeContext <TSaga, T> context) where T : class
        {
            if (context.TryGetPayload <Scope>(out var existingScope))
            {
                existingScope.UpdateScope(context);

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

            var scope = AsyncScopedLifestyle.BeginScope(_container);

            try
            {
                scope.UpdateScope(context);

                var proxy = new SagaQueryConsumeContextProxy <TSaga, T>(context, new PayloadCacheScope(context), context.Query);

                proxy.UpdatePayload(scope);

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

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

                throw;
            }
        }
コード例 #14
0
        public ISagaQueryScopeContext <TSaga, T> GetQueryScope <T>(SagaQueryConsumeContext <TSaga, T> context)
            where T : class
        {
            if (context.TryGetPayload <IContainer>(out var existingContainer))
            {
                return(new ExistingSagaQueryScopeContext <TSaga, T>(context));
            }

            var container = _container?.CreateNestedContainer(context) ?? _context?.CreateNestedContainer(context);

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

                var consumerContainer = container;
                proxy.GetOrAddPayload(() => consumerContainer);
                foreach (Action <ConsumeContext> scopeAction in _scopeActions)
                {
                    scopeAction(proxy);
                }

                return(new CreatedSagaQueryScopeContext <IContainer, TSaga, T>(consumerContainer, proxy));
            }
            catch
            {
                container.Dispose();

                throw;
            }
        }
コード例 #15
0
        public ISagaQueryScopeContext <TSaga, T> GetQueryScope <T>(SagaQueryConsumeContext <TSaga, T> context) where T : class
        {
            if (context.TryGetPayload <IServiceScope>(out var existingServiceScope))
            {
                return(new ExistingSagaQueryScopeContext <TSaga, T>(context));
            }

            var scopeFactory = _serviceProvider.GetRequiredService <IServiceScopeFactory>();
            var scope        = scopeFactory.CreateScope();

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

                var sagaScope = scope;
                proxy.GetOrAddPayload(() => sagaScope);
                foreach (Action <ConsumeContext> scopeAction in _scopeActions)
                {
                    scopeAction(proxy);
                }

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

                throw;
            }
        }
コード例 #16
0
 public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
     where T : class
 {
     using (_container.GetNestedContainer())
     {
         await _repository.SendQuery(context, policy, next);
     }
 }
コード例 #17
0
 public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
     where T : class
 {
     using (_container.CreateChildContainer())
     {
         await _repository.SendQuery(context, policy, next).ConfigureAwait(false);
     }
 }
コード例 #18
0
 async Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
 {
     using (var nestedContainer = _container.GetNestedContainer())
     {
         SagaQueryConsumeContext <TSaga, T> proxy = context.CreateQueryScope(nestedContainer);
         await _repository.SendQuery(proxy, policy, next).ConfigureAwait(false);
     }
 }
コード例 #19
0
 async Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
                                                   IPipe <SagaConsumeContext <TSaga, T> > next)
 {
     using (_scope.BeginLifetimeScope(_name))
     {
         await _repository.SendQuery(context, policy, next);
     }
 }
コード例 #20
0
        public static SagaQueryConsumeContext <TSaga, T> CreateQueryScope <T, TSaga>(this SagaQueryConsumeContext <TSaga, T> context)
            where T : class
            where TSaga : class, ISaga
        {
            var proxy = new SagaQueryConsumeContextProxy <TSaga, T>(context, new PayloadCacheScope(context), context.Query);

            return(proxy);
        }
コード例 #21
0
 async Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
                                                   IPipe <SagaConsumeContext <TSaga, T> > next)
 {
     using (ISagaQueryScopeContext <TSaga, T> scope = _scopeProvider.GetQueryScope(context))
     {
         await _repository.SendQuery(scope.Context, policy, next).ConfigureAwait(false);
     }
 }
コード例 #22
0
        Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
                                                    IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            var interceptPipe   = new InterceptPipe <T>(_sagas, _received, next);
            var interceptPolicy = new InterceptPolicy <T>(_created, policy);

            return(_sagaRepository.SendQuery(context, interceptPolicy, interceptPipe));
        }
コード例 #23
0
        public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class
        {
            using (var scope = this._services.CreateScope())
            {
                SagaQueryConsumeContext <TSaga, T> proxy = context.CreateQueryScope(scope);

                await this._repository.SendQuery(proxy, policy, next).ConfigureAwait(false);
            }
        }
コード例 #24
0
        async Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
                                                          IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            var outerScope = _registry.GetLifetimeScope(GetScopeId(context));

            using (outerScope.BeginLifetimeScope(_name))
            {
                await _repository.SendQuery(context, policy, next).ConfigureAwait(false);
            }
        }
コード例 #25
0
        public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
            where T : class
        {
            using (var scope = _container.BeginExecutionContextScope())
            {
                SagaQueryConsumeContext <TSaga, T> proxy = context.CreateQueryScope(scope);

                await _repository.SendQuery(proxy, policy, next).ConfigureAwait(false);
            }
        }
コード例 #26
0
        async Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
                                                          IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            using (var lifetimeScope = _scope.BeginLifetimeScope(_name))
            {
                SagaQueryConsumeContext <TSaga, T> proxy = context.CreateQueryScope(lifetimeScope);

                await _repository.SendQuery(proxy, policy, next).ConfigureAwait(false);
            }
        }
コード例 #27
0
        async Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
                                                          IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            using (var nestedContainer = _container.GetNestedContainer())
            {
                SagaQueryConsumeContext <TSaga, T> proxy = context.CreateQueryScope(nestedContainer);

                proxy.GetOrAddPayload <IStateMachineActivityFactory>(() => new StructureMapStateMachineActivityFactory());

                await _repository.SendQuery(proxy, policy, next).ConfigureAwait(false);
            }
        }
コード例 #28
0
        async Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
                                                          IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            using (var lifetimeScope = _scope.BeginLifetimeScope(_name))
            {
                SagaQueryConsumeContext <TSaga, T> proxy = context.CreateQueryScope(lifetimeScope);

                proxy.GetOrAddPayload <IStateMachineActivityFactory>(() => new AutofacStateMachineActivityFactory());

                await _repository.SendQuery(proxy, policy, next).ConfigureAwait(false);
            }
        }
コード例 #29
0
        Task ISagaRepository <TSaga> .SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy,
                                                    IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            SagaInstance <TSaga>[] existingSagas = _sagas.Where(context.Query).ToArray();
            if (existingSagas.Length == 0)
            {
                var missingSagaPipe = new MissingPipe <T>(this, next);
                return(policy.Missing(context, missingSagaPipe));
            }

            return(Task.WhenAll(existingSagas.Select(instance => SendToInstance(context, policy, instance, next))));
        }
コード例 #30
0
        public async Task SendQuery <T>(SagaQueryConsumeContext <TSaga, T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next) where T : class
        {
            using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
                using (var connection = new SqlConnection(_connectionString))
                {
                    try
                    {
                        var tableName = GetTableName <T>();
                        var(whereStatement, parameters) = WhereStatementHelper.GetWhereStatementAndParametersFromExpression(context.Query.FilterExpression);

                        List <TSaga> instances =
                            (await connection.QueryAsync <TSaga>($"SELECT * FROM {tableName} WITH (UPDLOCK, ROWLOCK) {whereStatement}",
                                                                 parameters).ConfigureAwait(false)).ToList();

                        if (!instances.Any())
                        {
                            var missingSagaPipe = new MissingPipe <T>(connection, tableName, next, InsertSagaInstance);

                            await policy.Missing(context, missingSagaPipe);
                        }
                        else
                        {
                            foreach (var instance in instances)
                            {
                                await SendToInstance(context, connection, policy, instance, tableName, next).ConfigureAwait(false);
                            }
                        }

                        transaction.Complete();
                    }
                    catch (SagaException sex)
                    {
                        if (Log.IsErrorEnabled)
                        {
                            Log.Error($"SAGA:{TypeMetadataCache<TSaga>.ShortName} Exception {TypeMetadataCache<T>.ShortName}", sex);
                        }

                        throw;
                    }
                    catch (Exception ex)
                    {
                        if (Log.IsErrorEnabled)
                        {
                            Log.Error($"SAGA:{TypeMetadataCache<TSaga>.ShortName} Exception {TypeMetadataCache<T>.ShortName}", ex);
                        }

                        throw new SagaException(ex.Message, typeof(TSaga), typeof(T), Guid.Empty, ex);
                    }
                }
        }