Пример #1
0
            public async Task Send(SagaConsumeContext <TSaga, TMessage> context)
            {
                var instance = new SagaInstance <TSaga>(context.Saga);

                await instance.MarkInUse(context.CancellationToken).ConfigureAwait(false);

                try
                {
                    var proxy = new InMemorySagaConsumeContext <TSaga, TMessage>(context, context.Saga, () => RemoveNewSaga(instance, context.CancellationToken));

                    if (_withinLock)
                    {
                        _repository.AddWithinLock(instance);
                    }
                    else
                    {
                        await _repository.Add(instance, context.CancellationToken).ConfigureAwait(false);
                    }

                    if (_log.IsDebugEnabled)
                    {
                        _log.DebugFormat("SAGA:{0}:{1} Added {2}", TypeMetadataCache <TSaga> .ShortName, context.Saga.CorrelationId,
                                         TypeMetadataCache <TMessage> .ShortName);
                    }

                    try
                    {
                        await _next.Send(proxy).ConfigureAwait(false);

                        if (proxy.IsCompleted)
                        {
                            if (_log.IsDebugEnabled)
                            {
                                _log.DebugFormat("SAGA:{0}:{1} Removed {2}", TypeMetadataCache <TSaga> .ShortName, context.Saga.CorrelationId,
                                                 TypeMetadataCache <TMessage> .ShortName);
                            }

                            await RemoveNewSaga(instance, context.CancellationToken).ConfigureAwait(false);
                        }
                    }
                    catch (Exception)
                    {
                        if (_log.IsDebugEnabled)
                        {
                            _log.DebugFormat("SAGA:{0}:{1} Removed(Fault) {2}", TypeMetadataCache <TSaga> .ShortName, context.Saga.CorrelationId,
                                             TypeMetadataCache <TMessage> .ShortName);
                        }

                        await RemoveNewSaga(instance, context.CancellationToken).ConfigureAwait(false);

                        throw;
                    }
                }
                finally
                {
                    instance.Release();
                }
            }
Пример #2
0
        async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            if (!context.CorrelationId.HasValue)
            {
                throw new SagaException("The CorrelationId was not specified", typeof(TSaga), typeof(T));
            }

            var sagaId = context.CorrelationId.Value;

            var needToLeaveSagas = true;
            await _sagas.MarkInUse(context.CancellationToken).ConfigureAwait(false);

            try
            {
                SagaInstance <TSaga> saga = _sagas[sagaId];
                if (saga == null)
                {
                    var missingSagaPipe = new MissingPipe <T>(this, next, true);

                    await policy.Missing(context, missingSagaPipe).ConfigureAwait(false);

                    _sagas.Release();
                    needToLeaveSagas = false;
                }
                else
                {
                    await saga.MarkInUse(context.CancellationToken).ConfigureAwait(false);

                    try
                    {
                        _sagas.Release();
                        needToLeaveSagas = false;

                        if (_log.IsDebugEnabled)
                        {
                            _log.DebugFormat("SAGA:{0}:{1} Used {2}", TypeMetadataCache <TSaga> .ShortName, sagaId, 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();
                    }
                }
            }
            finally
            {
                if (needToLeaveSagas)
                {
                    _sagas.Release();
                }
            }
        }
Пример #3
0
 public void Remove(SagaInstance <TSaga> item)
 {
     lock (_lock)
     {
         foreach (IIndexedSagaProperty <TSaga> index in _indices.Values)
         {
             index.Remove(item);
         }
     }
 }
Пример #4
0
 public void Add(SagaInstance <TSaga> instance)
 {
     lock (_lock)
     {
         foreach (IIndexedSagaProperty <TSaga> index in _indices.Values)
         {
             index.Add(instance);
         }
     }
 }
Пример #5
0
 async Task RemoveNewSaga(SagaInstance <TSaga> instance, CancellationToken cancellationToken)
 {
     if (_withinLock)
     {
         _repository.RemoveWithinLock(instance);
     }
     else
     {
         await _repository.Remove(instance, cancellationToken).ConfigureAwait(false);
     }
 }
Пример #6
0
        public void Add(SagaInstance <TSaga> newItem)
        {
            var key = _getProperty(newItem.Instance);

            if (!_values.TryGetValue(key, out HashSet <SagaInstance <TSaga> > hashSet))
            {
                hashSet = new HashSet <SagaInstance <TSaga> >();
                _values.Add(key, hashSet);
            }

            hashSet.Add(newItem);
        }
Пример #7
0
        /// <summary>
        /// Add an instance to the saga repository
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task Add(SagaInstance <TSaga> instance, CancellationToken cancellationToken)
        {
            await _sagas.MarkInUse(cancellationToken).ConfigureAwait(false);

            try
            {
                _sagas.Add(instance);
            }
            finally
            {
                _sagas.Release();
            }
        }
        async Task Remove(SagaInstance <TSaga> saga, CancellationToken cancellationToken)
        {
            await _sagas.MarkInUse(cancellationToken).ConfigureAwait(false);

            try
            {
                _sagas.Remove(saga);
            }
            finally
            {
                _sagas.Release();
            }
        }
            public async Task Send(SagaConsumeContext <TSaga, TMessage> context)
            {
                var instance = new SagaInstance <TSaga>(context.Saga);

                await instance.MarkInUse(context.CancellationToken).ConfigureAwait(false);

                var activity = LogContext.IfEnabled(OperationName.Saga.Add)?.StartActivity(new { context.Saga.CorrelationId });

                try
                {
                    var sagaConsumeContext = new InMemorySagaConsumeContext <TSaga, TMessage>(context, context.Saga,
                                                                                              () => RemoveNewSaga(instance, context.CancellationToken));

                    if (_withinLock)
                    {
                        _repository.AddWithinLock(instance);
                    }
                    else
                    {
                        await _repository.Add(instance, context.CancellationToken).ConfigureAwait(false);
                    }

                    sagaConsumeContext.LogAdded();

                    try
                    {
                        await _next.Send(sagaConsumeContext).ConfigureAwait(false);

                        if (sagaConsumeContext.IsCompleted)
                        {
                            await RemoveNewSaga(instance, context.CancellationToken).ConfigureAwait(false);

                            sagaConsumeContext.LogRemoved();
                        }
                    }
                    catch (Exception exception)
                    {
                        await RemoveNewSaga(instance, context.CancellationToken).ConfigureAwait(false);

                        sagaConsumeContext.LogRemoved(exception);

                        throw;
                    }
                }
                finally
                {
                    instance.Release();

                    activity?.Stop();
                }
            }
Пример #10
0
        public void Remove(SagaInstance <TSaga> instance)
        {
            var key = _getProperty(instance.Instance);

            if (!_values.TryGetValue(key, out HashSet <SagaInstance <TSaga> > hashSet))
            {
                return;
            }

            if (hashSet.Remove(instance) && hashSet.Count == 0)
            {
                _values.Remove(key);
            }
        }
Пример #11
0
        public bool Equals(SagaInstance <TSaga> other)
        {
            if (ReferenceEquals(null, other))
            {
                return(false);
            }

            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            return(EqualityComparer <TSaga> .Default.Equals(_instance, other._instance));
        }
Пример #12
0
        void RemoveWithinLock(SagaInstance <TSaga> instance)
        {
            instance.Remove();

            _sagas.Remove(instance);
        }
Пример #13
0
 /// <summary>
 /// Adds the saga within an existing lock
 /// </summary>
 /// <param name="instance"></param>
 void AddWithinLock(SagaInstance <TSaga> instance)
 {
     _sagas.Add(instance);
 }
Пример #14
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();
            }
        }
Пример #15
0
        async Task ISagaRepository <TSaga> .Send <T>(ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy, IPipe <SagaConsumeContext <TSaga, T> > next)
        {
            if (!context.CorrelationId.HasValue)
            {
                throw new SagaException("The CorrelationId was not specified", typeof(TSaga), typeof(T));
            }

            var sagaId = context.CorrelationId.Value;

            await _sagas.MarkInUse(context.CancellationToken).ConfigureAwait(false);

            var needToLeaveSagas = true;

            try
            {
                SagaInstance <TSaga> saga = _sagas[sagaId];
                if (saga != null)
                {
                    await saga.MarkInUse(context.CancellationToken).ConfigureAwait(false);

                    try
                    {
                        _sagas.Release();
                        needToLeaveSagas = false;

                        if (saga.IsRemoved)
                        {
                            saga.Release();
                            saga = null;
                        }
                        else
                        {
                            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();
                    }
                }

                if (saga == null)
                {
                    var missingSagaPipe = new MissingPipe <T>(this, next, true);

                    await policy.Missing(context, missingSagaPipe).ConfigureAwait(false);

                    _sagas.Release();
                    needToLeaveSagas = false;
                }
            }
            finally
            {
                if (needToLeaveSagas)
                {
                    _sagas.Release();
                }
            }
        }
Пример #16
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();
            }
        }