Exemple #1
0
        private async Task <ISaga> ProcessSagaAsync(
            IDomainEvent domainEvent,
            ISagaId sagaId,
            SagaDetails details,
            CancellationToken cancellationToken)
        {
            try {
                _log.Verbose(() => $"Loading saga '{details.SagaType.PrettyPrint()}' with ID '{sagaId}'");

                return(await _sagaStore.UpdateAsync <ISaga>(
                           sagaId,
                           details,
                           domainEvent.Metadata.SourceId,
                           (s, c) => UpdateSagaAsync(s, domainEvent, details, c),
                           cancellationToken)
                       .ConfigureAwait(false));
            } catch (Exception e) {
                var handled = await _sagaErrorHandler.HandleAsync(
                    sagaId,
                    details,
                    e,
                    cancellationToken)
                              .ConfigureAwait(false);

                if (handled)
                {
                    return(null);
                }

                _log.Error(e,
                           $"Failed to process domain event '{domainEvent.EventType}' for saga '{details.SagaType.PrettyPrint()}'");
                throw;
            }
        }
        public async Task <TSaga> UpdateAsync <TSaga>(
            ISagaId sagaId,
            SagaDetails sagaDetails,
            ISourceId sourceId,
            Func <TSaga, CancellationToken, Task> updateSaga,
            CancellationToken cancellationToken)
            where TSaga : ISaga
        {
            var saga = default(TSaga);

            var storeAggregateSagaAsync = await GetUpdateAsync(
                sagaDetails.SagaType,
                cancellationToken)
                                          .ConfigureAwait(false);

            var domainEvents = await storeAggregateSagaAsync(
                sagaId,
                sourceId,
                async (s, c) => {
                var specificSaga = (TSaga)s;
                await updateSaga(specificSaga, c).ConfigureAwait(false);
                saga = specificSaga;
            },
                cancellationToken)
                               .ConfigureAwait(false);

            return(domainEvents.Any()
                ? saga
                : default(TSaga));
        }
Exemple #3
0
            public override async Task <ISaga> UpdateAsync(
                ISagaId sagaId,
                Type sagaType,
                ISourceId sourceId,
                Func <ISaga, CancellationToken, Task> updateSaga,
                CancellationToken cancellationToken)
            {
                var commandBus = _serviceProvider.GetRequiredService <ICommandBus>();

                ISaga saga;

                using (await _asyncLock.WaitAsync(cancellationToken).ConfigureAwait(false))
                {
                    _hasUpdateBeenCalled = true;

                    if (!_sagas.TryGetValue(sagaId, out var obj))
                    {
                        obj            = Activator.CreateInstance(sagaType, sagaId);
                        _sagas[sagaId] = obj;
                    }

                    saga = (ISaga)obj;

                    await updateSaga(saga, cancellationToken).ConfigureAwait(false);
                }

                await saga.PublishAsync(commandBus, cancellationToken).ConfigureAwait(false);

                return(saga);
            }
Exemple #4
0
            public async Task <TSaga> UpdateAsync <TSaga>(
                ISagaId sagaId,
                SagaDetails sagaDetails,
                ISourceId sourceId,
                Func <TSaga, CancellationToken, Task> updateSaga,
                CancellationToken cancellationToken)
                where TSaga : ISaga
            {
                using (await _asyncLock.WaitAsync(cancellationToken).ConfigureAwait(false))
                {
                    _hasUpdateBeenCalled = true;

                    if (!_sagas.TryGetValue(sagaId, out var obj))
                    {
                        obj            = Activator.CreateInstance(sagaDetails.SagaType, sagaId);
                        _sagas[sagaId] = obj;
                    }

                    var saga = (TSaga)obj;

                    await updateSaga(saga, cancellationToken).ConfigureAwait(false);

                    return(saga);
                }
            }
Exemple #5
0
 public Task <bool> HandleAsync(
     ISagaId sagaId,
     SagaDetails sagaDetails,
     Exception exception,
     CancellationToken cancellationToken)
 {
     // The default handler cannot handle anything!
     return(Task.FromResult(false));
 }
Exemple #6
0
 public async Task <TSaga> UpdateAsync <TSaga>(
     ISagaId sagaId,
     ISourceId sourceId,
     Func <TSaga, CancellationToken, Task> updateSaga,
     CancellationToken cancellationToken)
     where TSaga : ISaga
 {
     return((TSaga) await UpdateAsync(
                sagaId,
                typeof(TSaga),
                sourceId,
                (s, c) => updateSaga((TSaga)s, c),
                cancellationToken)
            .ConfigureAwait(false));
 }
Exemple #7
0
        private async Task ProcessSagaAsync(
            IDomainEvent domainEvent,
            ISagaId sagaId,
            SagaDetails details,
            CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogTrace(
                    "Loading saga {SagaType} with ID {Id}",
                    details.SagaType.PrettyPrint(),
                    sagaId);

                await _sagaStore.UpdateAsync(
                    sagaId,
                    details.SagaType,
                    domainEvent.Metadata.EventId,
                    (s, c) => UpdateSagaAsync(s, domainEvent, details, c),
                    cancellationToken)
                .ConfigureAwait(false);
            }
            catch (Exception e)
            {
                var handled = await _sagaErrorHandler.HandleAsync(
                    sagaId,
                    details,
                    e,
                    cancellationToken)
                              .ConfigureAwait(false);

                if (handled)
                {
                    return;
                }

                _logger.LogError(
                    "Failed to process domain event {DomainEventType} for saga {SagaType}",
                    domainEvent.EventType,
                    details.SagaType.PrettyPrint());
                throw;
            }
        }
        public override async Task <ISaga> UpdateAsync(
            ISagaId sagaId,
            Type sagaType,
            ISourceId sourceId,
            Func <ISaga, CancellationToken, Task> updateSaga,
            CancellationToken cancellationToken)
        {
            var saga = null as ISaga;

            var storeAggregateSagaAsync = await GetUpdateAsync(
                sagaType,
                cancellationToken)
                                          .ConfigureAwait(false);

            var domainEvents = await storeAggregateSagaAsync(
                this,
                sagaId,
                sourceId,
                async (s, c) =>
            {
                await updateSaga(s, c).ConfigureAwait(false);
                saga = s;
            },
                cancellationToken)
                               .ConfigureAwait(false);

            if (!domainEvents.Any())
            {
                return(null);
            }

            var commandBus = _resolver.Resolve <ICommandBus>();
            await saga.PublishAsync(commandBus, cancellationToken).ConfigureAwait(false);

            return(saga);
        }
Exemple #9
0
        private async Task ProcessSagaAsync(
            IDomainEvent domainEvent,
            ISagaId sagaId,
            SagaDetails details,
            CancellationToken cancellationToken)
        {
            try
            {
                _log.Verbose(() => $"Loading saga '{details.SagaType.PrettyPrint()}' with ID '{sagaId}'");

                await _sagaStore.UpdateAsync(
                    sagaId,
                    details.SagaType,
                    domainEvent.Metadata.EventId,
                    (s, c) => UpdateSagaAsync(s, domainEvent, details, c),
                    cancellationToken)
                .ConfigureAwait(false);
            }
            catch (Exception e)
            {
                // Search for a specific SagaErrorHandler<Saga> based on saga type
                ISagaErrorHandler specificSagaErrorHandler = _sagaErrorHandlerFactory(details.SagaType);

                bool handled = specificSagaErrorHandler != null ?
                               await specificSagaErrorHandler.HandleAsync(sagaId, details, e, cancellationToken).ConfigureAwait(false) :
                               await _sagaErrorHandler.HandleAsync(sagaId, details, e, cancellationToken).ConfigureAwait(false);

                if (handled)
                {
                    return;
                }

                _log.Error(e, $"Failed to process domain event '{domainEvent.EventType}' for saga '{details.SagaType.PrettyPrint()}'");
                throw;
            }
        }
Exemple #10
0
        public override async Task <ISaga> UpdateAsync(
            ISagaId sagaId,
            Type sagaType,
            ISourceId sourceId,
            Func <ISaga, CancellationToken, Task> updateSaga,
            CancellationToken cancellationToken)
        {
            var saga = null as ISaga;

            var storeAggregateSagaAsync = await GetUpdateAsync(
                sagaType,
                cancellationToken)
                                          .ConfigureAwait(false);

            await storeAggregateSagaAsync(
                this,
                sagaId,
                sourceId,
                async (s, c) =>
            {
                await updateSaga(s, c).ConfigureAwait(false);
                saga = s;
            },
                cancellationToken)
            .ConfigureAwait(false);

            if (saga is null)
            {
                return(null);
            }

            var commandBus = _serviceProvider.GetRequiredService <ICommandBus>();
            await saga.PublishAsync(commandBus, cancellationToken).ConfigureAwait(false);

            return(saga);
        }
Exemple #11
0
 public abstract Task <ISaga> UpdateAsync(
     ISagaId sagaId,
     Type sagaType,
     ISourceId sourceId,
     Func <ISaga, CancellationToken, Task> updateSaga,
     CancellationToken cancellationToken);
Exemple #12
0
 public Task <bool> HandleAsync(ISagaId sagaId, SagaDetails sagaDetails, Exception exception,
                                CancellationToken cancellationToken)
 {
     return(Task.FromResult(true));
 }