예제 #1
0
        public void FlagSubscriptionAsPoisoned(IEvent poisonedEvent, PoisonMessageException exception)
        {
            using (var context = this.contextFactory.Invoke(false))
            {
                var subscription = context.Subscriptions.Where(s => s.StreamType == poisonedEvent.StreamType && s.SubscriberStreamType == this.streamType).Single();
                subscription.IsPoisoned      = true;
                subscription.UpdateLocalTime = this.time.Now.ToLocalTime();
                subscription.PoisonEventCollectionVersion = poisonedEvent.EventCollectionVersion;
                try
                {
                    subscription.ExceptionMessage = this.serializer.Serialize(exception);
                }
                catch (Exception)
                {
                    subscription.ExceptionMessage = string.Format("Exception type: {0}. Exception message: {1}. Inner exception: {2}", exception.GetType().Name, exception.Message, exception.InnerException.Message != null ? exception.InnerException.Message : "null");
                }
                try
                {
                    subscription.DeadLetterPayload = this.serializer.Serialize(poisonedEvent);
                }
                catch (Exception)
                {
                    subscription.DeadLetterPayload = string.Format("EventType: {0}", poisonedEvent.GetType().Name);
                }

                context.SaveChanges();
            }
        }
예제 #2
0
        public void Create_Inner()
        {
            var e = new PoisonMessageException("error", new Exception(), Substitute.For <IMessageId>(), Substitute.For <ICorrelationId>(), null, null);

            Assert.Equal("error", e.Message);
            Assert.NotNull(e.InnerException);
        }
예제 #3
0
        /// <inheritdoc />
        public void Handle(IMessageContext context, PoisonMessageException exception)
        {
            var header = _getHeader.GetHeaders(context.MessageId);

            if (header != null)
            {
                var activityContext = header.Extract(_tracer, _headers);
                using (var scope = _tracer.StartActivity("PoisonMessage", ActivityKind.Internal, activityContext))
                {
                    scope?.AddMessageIdTag(context);
                    scope?.RecordException(exception);
                    scope?.SetStatus(Status.Error);
                    _handler.Handle(context, exception);
                }
            }
            else
            {
                using (var scope = _tracer.StartActivity("PoisonMessage"))
                {
                    scope?.AddMessageIdTag(context);
                    scope?.RecordException(exception);
                    _handler.Handle(context, exception);
                }
            }
        }
예제 #4
0
 /// <summary>
 /// Invoked when we have dequeued a message, but a failure occurred during re-assembly.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="exception">The exception.</param>
 public void Handle(IMessageContext context, PoisonMessageException exception)
 {
     if (context.MessageId != null && context.MessageId.HasValue)
     {
         _commandMoveRecord.Handle(new MoveRecordToErrorQueueCommand <string>(exception, context.MessageId.Id.Value.ToString(), context));
     }
     context.SetMessageAndHeaders(null, context.Headers);
 }
예제 #5
0
        public void Create_Empty()
        {
            var e = new PoisonMessageException();

            Assert.Equal("Exception of type 'DotNetWorkQueue.Exceptions.PoisonMessageException' was thrown.", e.Message);
            Assert.Null(e.HeaderPayload);
            Assert.Null(e.MessagePayload);
        }
예제 #6
0
 /// <summary>
 /// Invoked when we have dequeued a message, but a failure occurred during re-assembly.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="exception">The exception.</param>
 public void Handle(IMessageContext context, PoisonMessageException exception)
 {
     if (context.MessageId != null && context.MessageId.HasValue)
     {
         _commandMoveRecord.Handle(new MoveRecordToErrorQueueCommand((RedisQueueId)context.MessageId));
     }
     context.SetMessageAndHeaders(null, context.Headers);
 }
예제 #7
0
        public void FlagSubscriptionAsPoisoned(IEvent poisonedEvent, PoisonMessageException exception)
        {
            var sub = this.subscriptions.Where(s => s.StreamType == poisonedEvent.StreamType && s.SubscriberStreamType == this.streamType).Single();

            sub.IsPoisoned      = true;
            sub.UpdateLocalTime = this.time.Now.ToLocalTime();
            sub.PoisonEventCollectionVersion = poisonedEvent.EventCollectionVersion;
            sub.ExceptionMessage             = this.serializer.Serialize(exception);
            sub.DeadLetterPayload            = this.serializer.Serialize(poisonedEvent);
        }
예제 #8
0
        /// <summary>
        /// Invoked when we have dequeued a message, but a failure occured during re-assembly.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="exception">The exception.</param>
        public void Handle(IMessageContext context, PoisonMessageException exception)
        {
            Guard.NotNull(() => context, context);
            Guard.NotNull(() => exception, exception);

            if (context.MessageId == null || !context.MessageId.HasValue)
            {
                return;
            }

            _dataStorage.MoveToErrorQueue(exception, (Guid)context.MessageId.Id.Value, context);
            context.SetMessageAndHeaders(null, context.Headers);
        }
예제 #9
0
 /// <summary>
 /// Invoked when we have dequeued a message, but a failure occurred during re-assembly.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="exception">The exception.</param>
 public void Handle(IMessageContext context, PoisonMessageException exception)
 {
     if (context.MessageId != null && context.MessageId.HasValue)
     {
         var messageId = context.MessageId.Id.Value.ToString();
         _handler.Handle(context, exception);
         _log.LogError(
             $"Message with ID {messageId} has failed after de-queue, but before finishing loading. This message is considered a poison message, and has been moved to the error queue{System.Environment.NewLine}{exception}");
     }
     else
     {
         _handler.Handle(context, exception);
     }
 }
예제 #10
0
 /// <summary>
 /// Invoked when we have dequeued a message, but a failure occurred during re-assembly.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="exception">The exception.</param>
 public void Handle(IMessageContext context, PoisonMessageException exception)
 {
     if (context.MessageId != null && context.MessageId.HasValue)
     {
         var messageId = context.MessageId.Id.Value.ToString();
         _handler.Handle(context, exception);
         _log.ErrorException(
             "Message with ID {0} has failed after de-queue, but before finishing loading. This message is considered a poison message, and has been moved to the error queue",
             exception,
             messageId);
     }
     else
     {
         _handler.Handle(context, exception);
     }
 }
        /// <inheritdoc />
        public void Handle(IMessageContext context, PoisonMessageException exception)
        {
            Guard.NotNull(() => context, context);
            Guard.NotNull(() => exception, exception);

            if (context.MessageId == null || !context.MessageId.HasValue)
            {
                return;
            }

            var messageId = (T)context.MessageId.Id.Value;

            _commandMoveRecord.Handle(
                new MoveRecordToErrorQueueCommand <T>(exception, messageId, context));
            context.SetMessageAndHeaders(null, context.Headers);
        }
        public void FlagSubscriptionAsPoisoned(IEvent poisonedEvent, PoisonMessageException exception)
        {
            string exceptionMessage;

            try
            {
                exceptionMessage = this.serializer.Serialize(exception);
            }
            catch (Exception)
            {
                exceptionMessage = string.Format("Exception type: {0}. Exception message: {1}. Inner exception: {2}", exception.GetType().Name, exception.Message, exception.InnerException.Message != null ? exception.InnerException.Message : "null");
            }

            string deadLetterPayload;

            try
            {
                deadLetterPayload = this.serializer.Serialize(poisonedEvent);
            }
            catch (Exception)
            {
                deadLetterPayload = string.Format("EventType: {0}", poisonedEvent.GetType().Name);
            }

            this.sql.ExecuteNonQuery(this.markAsPoisoned,
                                     new SqlParameter("@UpdateLocalTime", this.time.Now.ToLocalTime()),
                                     new SqlParameter("@PoisonEventCollectionVersion", poisonedEvent.EventCollectionVersion),
                                     new SqlParameter("@ExceptionMessage", SqlDbType.NVarChar)
            {
                Value = exceptionMessage
            },
                                     new SqlParameter("@DeadLetterPayload", SqlDbType.NVarChar)
            {
                Value = deadLetterPayload
            },
                                     new SqlParameter("@SubscriberStreamType", this.streamType),
                                     new SqlParameter("@StreamType", poisonedEvent.StreamType));
        }
        /// <inheritdoc />
        public void Handle(IMessageContext context, PoisonMessageException exception)
        {
            var header = _getHeader.GetHeaders(context.MessageId);

            if (header != null)
            {
                var spanContext = header.Extract(_tracer, _headers);
                if (spanContext != null)
                {
                    using (IScope scope = _tracer.BuildSpan("PoisonMessage").AddReference(References.FollowsFrom, spanContext).StartActive(finishSpanOnDispose: true))
                    {
                        scope.Span.Log(exception.ToString());
                        Tags.Error.Set(scope.Span, true);
                        _handler.Handle(context, exception);
                    }
                }
                else
                {
                    using (IScope scope = _tracer.BuildSpan("PoisonMessage").StartActive(finishSpanOnDispose: true))
                    {
                        scope.Span.AddMessageIdTag(context);
                        scope.Span.Log(exception.ToString());
                        Tags.Error.Set(scope.Span, true);
                        _handler.Handle(context, exception);
                    }
                }
            }
            else
            {
                using (IScope scope = _tracer.BuildSpan("PoisonMessage").StartActive(finishSpanOnDispose: true))
                {
                    scope.Span.AddMessageIdTag(context);
                    scope.Span.Log(exception.ToString());
                    _handler.Handle(context, exception);
                }
            }
        }
예제 #14
0
        public void Create_Format()
        {
            var e = new PoisonMessageException(Substitute.For <IMessageId>(), Substitute.For <ICorrelationId>(), null, null, "error {0}", 1);

            Assert.Equal("error 1", e.Message);
        }
 public IncomingEventIsPoisoned(IEvent poisonedEvent, PoisonMessageException exception)
 {
     this.PoisonedEvent = poisonedEvent;
     this.Exception = exception;
 }
예제 #16
0
 public void Handle(IMessageContext context, PoisonMessageException exception)
 {
 }
예제 #17
0
 /// <summary>
 /// Invoked when we have dequeued a message, but a failure occurred during re-assembly.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="exception">The exception.</param>
 public void Handle(IMessageContext context, PoisonMessageException exception)
 {
     _handler.Handle(context, exception);
     _meterError.Mark();
 }
예제 #18
0
        public void Create_HeaderPayload(byte[] header)
        {
            var e = new PoisonMessageException("error", Substitute.For <IMessageId>(), Substitute.For <ICorrelationId>(), null, header);

            Assert.Equal(header, e.HeaderPayload);
        }
예제 #19
0
        public void Create_MessagePayload(byte[] message)
        {
            var e = new PoisonMessageException("error", Substitute.For <IMessageId>(), Substitute.For <ICorrelationId>(), message, null);

            Assert.Equal(message, e.MessagePayload);
        }
예제 #20
0
        private void HandleGracefully(IEvent incomingEvent)
        {
            try
            {
                dynamic          me       = this;
                IMessageHandling handling = me.Handle((dynamic)incomingEvent);

                if (handling.ShouldBeIgnored)
                {
                    this.Ignore(incomingEvent);
                    return;
                }

                /*****************************************************
                 *  This was the old way to get a lock.
                 *
                 *  this.streamLocksById.TryAdd(id, new object());
                 *  lock (this.streamLocksById.TryGetValue(id))
                 *
                 ******************************************************/
                lock (this.streamLocksById.GetOrAdd(handling.StreamId.ToString(), new object()))
                {
                    try
                    {
                        if (!this.poisonedStreams.Where(p => p == handling.StreamId).Any())
                        {
                            this.HandleAndSaveChanges(incomingEvent, handling);
                        }

                        if (this.log.Verbose)
                        {
                            this.log.Trace($"{name} successfully handled message of type {incomingEvent.GetType().Name}");
                        }
                    }
                    catch (StreamNotFoundException ex)
                    {
                        // we igonore it, just to protect our servers to get down.
                        this.log.Error(ex, $"The stream {handling.StreamId} was not found. Ignoring message. You can retry by reseting the subscription table.");
                        this.Ignore(incomingEvent);
                    }
                    catch (RuntimeBinderException ex)
                    {
                        var list = new List <string>();
                        list.Add($"The state of {name} seems like it does not have an orveload to update when message of type {incomingEvent.GetType().Name} is processed. Did you forget to write a When-Event-like method?");
                        list.Add("-----------------------------------------------------------------------------------");
                        this.log.Error(ex, "", list.ToArray());
                        this.poisonedStreams.Add(handling.StreamId);
                        throw ex;
                    }
                    catch (Exception ex)
                    {
                        this.log.Error(ex, $"An error was detected while processing a message. Now we will try to check if it is duplicate or the snapshot is currupted");

                        // Maybe is duplicate
                        try
                        {
                            if (this.store.IsDuplicate(incomingEvent.EventId))
                            {
                                this.Ignore(incomingEvent);
                                return;
                            }
                        }
                        catch (Exception duplicateEx)
                        {
                            this.log.Error(duplicateEx, "An error ocurred while checking if incoming message is duplicate.");
                        }

                        // Or maybe the snapshot is corrupted
                        try
                        {
                            this.store.DeleteSnapshot(handling.StreamId);
                            this.HandleAndSaveChanges(incomingEvent, handling);
                            return;
                        }
                        catch (Exception deleteSnapshotEx)
                        {
                            this.log.Error(deleteSnapshotEx, "An error ocurred while deleting snapshot and trying to re-process a message.");
                        }

                        this.poisonedStreams.Add(handling.StreamId);
                        throw ex;
                    }
                }
            }
            catch (Exception ex)
            {
                var exception = new PoisonMessageException("An error ocurred in Event Processor while processing a message. The message will be marked as poisoned in order to review it. Maybe is just a dynamic binding error.", ex);

                this.bus.Publish(new IncomingEventIsPoisoned(incomingEvent, exception));

                this.log.Error(exception, $"Poison message of type {incomingEvent.GetType().Name} detected in Event Processor");
            }
        }
예제 #21
0
 public void FlagSubscriptionAsPoisoned(IEvent poisonedEvent, PoisonMessageException exception)
 {
     throw new InvalidOperationException("An error ocurred while trying to query a node");
 }
예제 #22
0
        public void Create()
        {
            var e = new PoisonMessageException("error", Substitute.For <IMessageId>(), Substitute.For <ICorrelationId>(), null, null);

            Assert.Equal("error", e.Message);
        }
 public IncomingEventIsPoisoned(IEvent poisonedEvent, PoisonMessageException exception)
 {
     this.PoisonedEvent = poisonedEvent;
     this.Exception     = exception;
 }