Ejemplo n.º 1
0
        public EventMessage Receive(TimeSpan timeout)
        {
            Message message = Link.Receive(timeout);

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

            var messageTypeName = message.ApplicationProperties[Constants.MESSAGE_TYPE_KEY] as string;

            if (!EventTypeLookup.ContainsKey(messageTypeName))
            {
                Logger.LogError($"Message {message.Properties.MessageId} rejected because message type was not registered for type {messageTypeName}");
                Link.Reject(message);
                return(null);
            }

            var dataType = EventTypeLookup[messageTypeName];

            Logger.LogDebug($"Event type: {dataType}");

            dynamic domainEvent;

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

            return(new EventMessage(domainEvent, message, Link));
        }
Ejemplo n.º 2
0
        protected async Task OnMessageCallbackAsync(IReceiverLink receiver, 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);
            }

            var timer = new Stopwatch();

            timer.Start();

            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;
                    }

                    timer.Stop();
                    var duration = timer.ElapsedMilliseconds;

                    var dp = new Dictionary <string, object> {
                        ["duration"] = duration
                    };

                    using (Logger.BeginScope(dp)) {
                        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);

                            using (var ts = new TransactionScope()) {
                                var sender = new SenderLink(Link.Session, Settings.AppName + "-retry", Settings.Queue);
                                // 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;
                                sender.Send(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) {
                    timer.Stop();
                    var duration = timer.ElapsedMilliseconds;

                    var dp = new Dictionary <string, object> {
                        ["duration"] = duration
                    };

                    using (Logger.BeginScope(dp)) {
                        Logger.LogError(ex, $"Message {message.Properties.MessageId} rejected because of unhandled exception {ex.Message}");
                        receiver.Reject(message);
                    }
                }
            }
        }
Ejemplo n.º 3
0
 internal EventMessage(DomainEventMessage domainEvent, Message message, IReceiverLink link)
 {
     this.message     = message;
     this.link        = link;
     this.domainEvent = domainEvent;
 }