private IDomainEvent?CreateEvent(DomainEventMessage message)
        {
            var types = this.GetType().Assembly.GetTypes();
            var type  = types.FirstOrDefault(x => x.Name == message.EventType);

            if (type == null)
            {
                return(null);
            }

            try
            {
                var domainEvent = Activator.CreateInstance(type);
                var properties  = type.GetProperties().Where(x => x.CanRead && x.CanWrite).ToDictionary(x => x.Name, x => x);
                foreach (var p in properties)
                {
                    if (message.Data.ContainsKey(p.Key))
                    {
                        p.Value.SetValue(domainEvent, Convert.ChangeType(message.Data[p.Key], p.Value.PropertyType));
                    }
                }
                return((IDomainEvent)domainEvent !);
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message);
                return(null);
            }
        }
        public async Task <HandlerResult> HandleAsync(DomainEventMessage <TestEvent> @event)
        {
            var properties = new Dictionary <string, object> {
                ["CorrelationId"] = @event.CorrelationId,
                ["MessageId"]     = @event.MessageId,
                ["MessageType"]   = @event.MessageTypeName
            };

            using (logger.BeginScope(properties)) {
                TestEvent.Instances.Add(@event.MessageId, @event.Data);

                if (@event.Data.IntValue == int.MinValue)
                {
                    var x = 0;
                    _ = 1 / x;
                }

                if (@event.Data.IntValue > 0)
                {
                    return(await Task.FromResult(HandlerResult.Success).ConfigureAwait(false));
                }
                else if (@event.Data.IntValue == 0)
                {
                    return(await Task.FromResult(HandlerResult.Retry).ConfigureAwait(false));
                }
                else
                {
                    return(await Task.FromResult(HandlerResult.Failed).ConfigureAwait(false));
                }
            }
        }
        public async Task <HandlerResult> HandleAsync(DomainEventMessage <WidgetStageChangedEvent> @event)
        {
            using (LogContext.PushProperty("MessageId", @event.MessageId))
                using (LogContext.PushProperty("CorrelationId", @event.CorrelationId))
                    using (LogContext.PushProperty("WidgetId", @event.Data.WidgetId)) {
                        logger.LogDebug($"Handling {typeof(WidgetStageChangedEvent).Name} for WebApiStarter {@event.Data.WidgetId}");

                        using (IServiceScope scope = serviceProvider.CreateScope()) {
                            var service      = scope.ServiceProvider.GetRequiredService <IWidgetService>();
                            var lockProvider = scope.ServiceProvider.GetRequiredService <IDistributedLockProvider>();
                            var lockName     = $"WidgetId:{@event.Data.WidgetId}";

                            logger.LogDebug($"Acquiring lock for {lockName}");
                            await using (await lockProvider.AcquireLockAsync(lockName).ConfigureAwait(false)) {
                                logger.LogDebug($"Acquired lock for {lockName}");
                                var entity = await service.GetWidget(@event.Data.WidgetId).ConfigureAwait(false);

                                // simulate more work with sleep
                                Thread.Sleep(TimeSpan.FromSeconds(5));
                                logger.LogInformation($"widget was observed changing it's state with body: {JsonConvert.SerializeObject(@event.Data)} and entity: {JsonConvert.SerializeObject(entity)}");
                            }
                        }

                        logger.LogDebug($"Successfully handled {typeof(WidgetStageChangedEvent).Name} for WebApiStarter {@event.Data.WidgetId}");
                        return(HandlerResult.Success);
                    }
        }
        private async Task HandleMessage <TMessage>(DomainEventMessage <TMessage> message, CancellationToken ct)
        {
            using (var repository = _repositoryFactory())
            {
                var correlationId = message.CorrelationId;

                if (false == correlationId.HasValue)
                {
                    return;
                }

                var processId = _buildId(correlationId.Value);

                var process = await repository.GetById <TProcess>(processId, _bucketId);

                process.ApplyEvent(message.DomainEvent);

                var undispatched = process.GetUndispatchedCommands()
                                   .Select(_dispatcher.Dispatch);

                await Task.WhenAll(undispatched);

                var commitId = _buildCommitId(message.Commit.CommitId, processId);

                await repository.Save(process, commitId, bucketId : _bucketId);
            }
        }
 /// <summary>
 /// Handle message event
 /// </summary>
 /// <param name="event"></param>
 /// <returns></returns>
 public async Task Handle(DomainEventMessage <SqlReportApiCreationEvent> @event)
 {
     using (LogContext.PushProperty("MessageId", @event.MessageId))
         using (LogContext.PushProperty("CorrelationId", @event.CorrelationId)) {
             await Handle(@event.Data);
         }
 }
Exemple #6
0
        public void ShouldBeAbleToAssignData()
        {
            // act
            var @event = new DomainEventMessage()
            {
                Data = new TestEvent()
            };

            // assert
            Assert.IsType <TestEvent>(@event.Data);
        }
        public async Task <HandlerResult> HandleAsync(DomainEventMessage <TestEvent> @event)
        {
            var properties = new Dictionary <string, object> {
                ["CorrelationId"] = @event.CorrelationId,
                ["MessageId"]     = @event.MessageId,
                ["MessageType"]   = @event.MessageTypeName
            };

            var correlationId = CorrelationContext.GetCorrelationId();

            if (@event.Data.IntValue == Int32.MaxValue && correlationId != @event.CorrelationId)
            {
                throw new ArgumentException($"CorrelationId {@event.CorrelationId} should equal {correlationId}");
            }

            using (logger.BeginScope(properties)) {
                TestEvent.Instances.Add(@event.MessageId, @event.Data);

                if (@event.Data.IntValue == int.MinValue)
                {
                    var x = 0;
                    _ = 1 / x;
                }

                if (@event.Data.IntValue > 0)
                {
                    return(await Task.FromResult(HandlerResult.Success).ConfigureAwait(false));
                }
                else if (@event.Data.IntValue == 0)
                {
                    return(await Task.FromResult(HandlerResult.Retry).ConfigureAwait(false));
                }
                else
                {
                    return(await Task.FromResult(HandlerResult.Failed).ConfigureAwait(false));
                }
            }
        }
 public Task Handle(DomainEventMessage <TestEvent> @event)
 {
     TestEvent.Instance      = @event.Data;
     TestEvent.CorrelationId = @event.CorrelationId;
     return(Task.FromResult(0));
 }
        private async Task OnMessageCallbackAsync(Message message)
        {
            var messageTypeName = message.ApplicationProperties[Constants.MESSAGE_TYPE_KEY] as string;
            var properties      = new Dictionary <string, object> {
                ["CorrelationId"] = message.Properties.CorrelationId,
                ["MessageId"]     = message.Properties.MessageId,
                ["MessageType"]   = messageTypeName
            };

            // if message has correlationId, set it so that handling can be found by initial correlation
            if (!string.IsNullOrWhiteSpace(message.Properties.CorrelationId))
            {
                CorrelationContext.SetCorrelationId(message.Properties.CorrelationId);
            }

            using (logger.BeginScope(properties)) {
                logger.LogInformation($"Received message {message.Properties.MessageId}");

                try {
                    string body = DomainEventMessage.GetBody(message);
                    logger.LogTrace("Received message {MessageId} with body: {MessageBody}", message.Properties.MessageId, body);

                    logger.LogDebug($"Event type key: {messageTypeName}");
                    if (!eventTypeLookup.ContainsKey(messageTypeName))
                    {
                        logger.LogError($"Message {message.Properties.MessageId} rejected because message type was not registered for type {messageTypeName}");
                        receiver.Reject(message);
                        return;
                    }

                    var dataType = eventTypeLookup[messageTypeName];
                    logger.LogDebug($"Event type: {dataType}");
                    var handlerType = typeof(IDomainEventHandler <>).MakeGenericType(dataType);
                    logger.LogDebug($"Event type handler interface: {handlerType}");
                    var handler = provider.GetService(handlerType);
                    if (handler == null)
                    {
                        logger.LogError($"Message {message.Properties.MessageId} rejected because handler was not found for type {messageTypeName}");
                        receiver.Reject(message);
                        return;
                    }
                    logger.LogDebug($"Event type handler: {handler.GetType()}");

                    dynamic domainEvent;
                    try {
                        domainEvent = DomainEventMessage.CreateGenericInstance(dataType, message);
                        logger.LogDebug($"Successfully deserialized body to {dataType}");
                    } catch (Exception ex) {
                        logger.LogError(ex, ex.Message);
                        receiver.Reject(message);
                        return;
                    }

                    HandlerResult result;
                    dynamic       dhandler = handler;
                    try {
                        result = await dhandler.HandleAsync(domainEvent).ConfigureAwait(false);
                    } catch (Exception ex) {
                        logger.LogError(ex, $"Message {message.Properties.MessageId} caught unhandled exception {ex.Message}");
                        result = HandlerResult.Failed;
                    }
                    logger.LogInformation($"Handler executed for message {message.Properties.MessageId} and returned result of {result}");

                    switch (result)
                    {
                    case HandlerResult.Success:
                        receiver.Accept(message);
                        logger.LogInformation($"Message {message.Properties.MessageId} accepted");
                        break;

                    case HandlerResult.Retry:
                        var deliveryCount = message.Header.DeliveryCount;
                        var delay         = 10 * deliveryCount;
                        var scheduleTime  = DateTime.UtcNow.AddSeconds(delay);

                        // create a new message to be queued with scheduled delivery time
                        var retry = new Message(body)
                        {
                            Header                = message.Header,
                            Footer                = message.Footer,
                            Properties            = message.Properties,
                            ApplicationProperties = message.ApplicationProperties
                        };
                        retry.ApplicationProperties[Constants.SCHEDULED_ENQUEUE_TIME_UTC] = scheduleTime;
                        receiver.Enqueue(retry);
                        receiver.Accept(message);
                        logger.LogInformation($"Message {message.Properties.MessageId} requeued with delay of {delay} seconds for {scheduleTime}");
                        break;

                    case HandlerResult.Failed:
                        receiver.Reject(message);
                        break;

                    case HandlerResult.Release:
                        receiver.Release(message);
                        break;

                    default:
                        throw new NotImplementedException($"Unknown HandlerResult value of {result}");
                    }
                } catch (Exception ex) {
                    logger.LogError(ex, $"Message {message.Properties.MessageId} rejected because of unhandled exception {ex.Message}");
                    receiver.Reject(message);
                }
            }
        }