public string ProcessMessage(IInboundMessage message)
        {
            if (message == null) throw new ArgumentNullException(nameof(message));

            var messageContextFactory = new MessageContextFactory(_synonymService, _areaService);
            var messageContext = messageContextFactory.Create(message);

            string answer;
            try
            {
                answer = ProcessMessage(messageContext);

                if (messageContext.GetContainsWord("debug"))
                {
                     answer += Environment.NewLine + Environment.NewLine + GenerateDebugOutput(messageContext);
                }
            }
            catch (Exception exception)
            {
                answer = $"{Emoji.Scream} Mist! Da ist etwas total schief gelaufen! Bitte stelle mir nie wieder solche Fragen!";
                Log.Error(exception, $"Error while processing message '{message.Text}'.");
            }

            return answer;
        }
        public async Task <byte[]> JoinIfComplete(IInboundMessage message)
        {
            var(messageId, chunkId, chunksCount) = ExtractHeadersValues(message);

            var count = await _store.CountChunks(messageId);

            if (count >= chunksCount - 1)
            {
                var chunks = await _store.GetChunks(messageId);

                if (chunks.ContainsKey(chunkId))
                {
                    return(null);
                }

                chunks.Add(chunkId, message.RawContent);

                var completeMessage = Join(chunks);

                await _store.Cleanup(messageId);

                return(completeMessage);
            }
            else
            {
                await _store.Store(messageId, chunkId, chunksCount, message.RawContent);

                return(null);
            }
        }
示例#3
0
        public void ProcessMessage(IInboundMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var synonymService        = _controller.GetService <SynonymService>();
            var messageContextFactory = new MessageContextFactory(synonymService);

            _messageContext = messageContextFactory.Create(message);

            try
            {
                Answer = ProcessMessage();

                if (_messageContext.GetContainsWord("debug"))
                {
                    Answer += Environment.NewLine + Environment.NewLine + GenerateDebugOutput();
                }
            }
            catch (Exception exception)
            {
                Answer = $"{Emoji.Scream} Mist! Da ist etwas total schief gelaufen! Bitte stelle mir nie wieder solche Fragen!";
                Log.Error(exception, $"Error while processing message '{message.Text}'.");
            }
        }
示例#4
0
        public async Task AddMessage(IInboundMessage message)
        {
            // TODO: Check this!
            if (_processingException != null)
            {
                throw new SilverbackException("Cannot add to the batch because the processing of the previous batch failed. See inner exception for details.", _processingException);
            }

            await _semaphore.WaitAsync();

            try
            {
                _messages.Add(message);

                _messageLogger.LogInformation(_logger, "Message added to batch.", message);

                if (_messages.Count == 1)
                {
                    CurrentBatchId = Guid.NewGuid();
                    _waitTimer?.Start();
                }
                else if (_messages.Count == _settings.Size)
                {
                    await ProcessBatch();
                }
            }
            finally
            {
                _semaphore.Release();
            }
        }
        private void WebSocketOnMessage(object sender, MessageEventArgs args)
        {
            string          messageJson = args?.Data ?? "";
            IInboundMessage baseMessage = _interpreter.InterpretMessage(messageJson);

            OnMessage?.Invoke(sender, baseMessage);
        }
示例#6
0
        public void AddMessage(IInboundMessage message)
        {
            // TODO: Check this!
            if (_processingException != null)
            {
                throw new SilverbackException("Cannot add to the batch because the processing of the previous batch failed. See inner exception for details.", _processingException);
            }

            lock (_messages)
            {
                _messages.Add(message);

                _messageLogger.LogInformation(_logger, "Message added to batch.", message, CurrentBatchId, CurrentSize);

                if (_messages.Count == 1)
                {
                    CurrentBatchId = Guid.NewGuid();
                    _waitTimer?.Start();
                }
                else if (_messages.Count == _settings.Size)
                {
                    ProcessBatch();
                }
            }
        }
示例#7
0
        protected override ErrorAction ApplyPolicy(IInboundMessage message, Exception exception)
        {
            ApplyDelay(message);

            _messageLogger.LogInformation(_logger, "The message will be processed again.", message);

            return(ErrorAction.Retry);
        }
示例#8
0
        private void PublishToNewEndpoint(IInboundMessage message, Exception exception)
        {
            message.Headers.AddOrReplace(MessageHeader.SourceEndpointKey, message.Endpoint?.Name);

            _producer.Produce(
                _transformationFunction?.Invoke(message.Content, exception) ?? message.Content ?? message.RawContent,
                _headersTransformationFunction?.Invoke(message.Headers, exception) ?? message.Headers);
        }
示例#9
0
        public void ApplyWhen_Exception_CanHandleReturnsExpectedResult(IInboundMessage message, Exception exception, bool mustApply)
        {
            var policy = (TestErrorPolicy) new TestErrorPolicy()
                         .ApplyWhen((msg, ex) => msg.Headers.GetValue <int>(MessageHeader.FailedAttemptsKey) <= 5 && ex.Message != "no");

            var canHandle = policy.CanHandle(message, exception);

            canHandle.Should().Be(mustApply);
        }
        private async Task ListenTo(IInboundMessage baseMessage)
        {
            if (baseMessage == null || baseMessage.MessageType == MessageType.Unknown)
            {
                return;
            }

            _inboundDataVisitor = new InboundDataVisitor(this);
            await baseMessage.Accept(_inboundDataVisitor);
        }
 private static void UpdateFailedAttemptsHeader(IInboundMessage message, int attempt)
 {
     if (message is IInboundBatch batch)
     {
         batch.Messages.ForEach(m => UpdateFailedAttemptsHeader(m, attempt));
     }
     else
     {
         message.Headers.AddOrReplace(MessageHeader.FailedAttemptsHeaderName, attempt.ToString());
     }
 }
示例#12
0
        private void ApplyDelay(IInboundMessage message)
        {
            var delay = _initialDelay.Milliseconds + message.FailedAttempts * _delayIncrement.Milliseconds;

            if (delay <= 0)
            {
                return;
            }

            _messageLogger.LogTrace(_logger, $"Waiting {delay} milliseconds before retrying the message.", message);
            Thread.Sleep(delay);
        }
示例#13
0
        public void LogProcessing(ILogger logger, IInboundMessage message)
        {
            var batch = message as IInboundBatch;

            LogInformation(logger,
                           batch != null
                    ? "Processing inbound batch."
                    : "Processing inbound message.",
                           message,
                           batch?.Id,
                           batch?.Size);
        }
        protected override bool MustProcess(IInboundMessage message, IServiceProvider serviceProvider)
        {
            var inboundLog = serviceProvider.GetRequiredService <IInboundLog>();

            if (inboundLog.Exists(message.Message, message.Endpoint))
            {
                return(false);
            }

            inboundLog.Add(message.Message, message.Endpoint);
            return(true);
        }
示例#15
0
 private void RelayAndCommitSingleMessage(IInboundMessage message, IServiceProvider serviceProvider)
 {
     try
     {
         _messagesHandler(new[] { message }, serviceProvider);
         Commit(new[] { message.Offset }, serviceProvider);
     }
     catch (Exception)
     {
         Rollback(serviceProvider);
         throw;
     }
 }
示例#16
0
 private void ProcessSingleMessage(IInboundMessage message)
 {
     _inboundMessageProcessor.TryDeserializeAndProcess(
         message,
         _errorPolicy,
         deserializedMessage =>
     {
         using (var scope = _serviceProvider.CreateScope())
         {
             RelayAndCommitSingleMessage(deserializedMessage, scope.ServiceProvider);
         }
     });
 }
示例#17
0
        public void LogProcessingError(ILogger logger, IInboundMessage message, Exception exception)
        {
            var batch = message as IInboundBatch;

            LogWarning(logger,
                       exception,
                       batch != null
                    ? "Error occurred processing the inbound batch."
                    : "Error occurred processing the inbound message.",
                       message,
                       batch?.Id,
                       batch?.Size);
        }
        public MessageContext(IInboundMessage originalMessage)
        {
            if (originalMessage == null) throw new ArgumentNullException(nameof(originalMessage));

            OriginalMessage = originalMessage;

            Words = new HashSet<string>();

            IdentifiedAreaIds = new HashSet<AreaId>();
            IdentifiedComponentIds = new HashSet<ComponentId>();
            FilteredComponentIds = new HashSet<ComponentId>();
            IdentifiedComponentStates = new HashSet<ComponentState>();
        }
示例#19
0
        protected override ErrorAction ApplyPolicy(IInboundMessage message, Exception exception)
        {
            foreach (var policy in _policies)
            {
                if (policy.CanHandle(message, exception))
                {
                    return(policy.HandleError(message, exception));
                }
            }

            _messageLogger.LogTrace(_logger, "All policies have been applied but the message still couldn't be successfully processed. The consumer will be stopped.", message);
            return(ErrorAction.StopConsuming);
        }
示例#20
0
        protected override async Task <bool> MustProcess(IInboundMessage message, IServiceProvider serviceProvider)
        {
            var inboundLog = serviceProvider.GetRequiredService <IInboundLog>();

            if (await inboundLog.Exists(message.Content, message.Endpoint))
            {
                return(false);
            }

            await inboundLog.Add(message.Content, message.Endpoint);

            return(true);
        }
        private async Task <IInboundMessage> HandleChunkedMessage(IInboundMessage message, IServiceProvider serviceProvider)
        {
            if (!message.Headers.Contains(MessageHeader.ChunkIdKey))
            {
                return(message);
            }

            var completeMessage = await serviceProvider.GetRequiredService <ChunkConsumer>().JoinIfComplete(message);

            return(completeMessage == null
                ? null
                : new InboundMessage(completeMessage, message.Headers, message.Offset, message.Endpoint, message.MustUnwrap));
        }
        protected override bool MustProcess(IInboundMessage message, IServiceProvider serviceProvider)
        {
            var offsetStore = serviceProvider.GetRequiredService <IOffsetStore>();

            var latest = offsetStore.GetLatestValue(message.Offset.Key);

            if (latest != null && message.Offset.CompareTo(latest) <= 0)
            {
                return(false);
            }

            offsetStore.Store(message.Offset);
            return(true);
        }
示例#23
0
        /// <summary>
        ///     Processes the inbound message.
        /// </summary>
        /// <param name="message">Message to process.</param>
        public void Process(IInboundMessage message)
        {
            var stateMessage = message as InboundStateMessage;

            if (stateMessage != null)
            {
                State = stateMessage.State;

                if (message is InboundSubscribeMessage)
                {
                    IsSubscribed = true;
                }
            }
        }
        public MessageContext Create(IInboundMessage message)
        {
            if (message == null) throw new ArgumentNullException(nameof(message));

            _currentContext = new MessageContext(message);

            IdentifyWords();

            IdentifyAreas();
            IdentifyComponents();
            IdentifyComponentStates();
            FilterComponentIds();

            return _currentContext;
        }
        public MessageContext(IInboundMessage originalMessage)
        {
            if (originalMessage == null)
            {
                throw new ArgumentNullException(nameof(originalMessage));
            }

            OriginalMessage = originalMessage;

            Words = new HashSet <string>();

            IdentifiedAreaIds         = new HashSet <AreaId>();
            IdentifiedComponentIds    = new HashSet <ComponentId>();
            IdentifiedComponentStates = new HashSet <IComponentState>();
        }
        private IInboundMessage DeserializeRawMessage(IInboundMessage message)
        {
            var deserialized =
                message.Content ?? (((InboundMessage)message).Content =
                                        message.Endpoint.Serializer.Deserialize(message.RawContent, message.Headers));

            // Create typed message for easier specific subscription
            var typedInboundMessage = (InboundMessage)Activator.CreateInstance(
                typeof(InboundMessage <>).MakeGenericType(deserialized.GetType()),
                message);

            typedInboundMessage.Content = deserialized;

            return(typedInboundMessage);
        }
示例#27
0
        public ErrorAction HandleError(IInboundMessage message, Exception exception)
        {
            var result = ApplyPolicy(message, exception);

            if (MessageToPublishFactory != null)
            {
                using (var scope = _serviceProvider.CreateScope())
                {
                    scope.ServiceProvider.GetRequiredService <IPublisher>()
                    .Publish(MessageToPublishFactory.Invoke(message));
                }
            }

            return(result);
        }
        public MessageContext Create(IInboundMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            _currentContext = new MessageContext(message);

            IdentifyWords();

            IdentifyAreas();
            IdentifyComponents();
            IdentifyComponentStates();

            return(_currentContext);
        }
示例#29
0
        private IInboundMessage HandleChunkedMessage(IInboundMessage message, IServiceProvider serviceProvider)
        {
            if (!(message.Message is MessageChunk chunk))
            {
                return(message);
            }

            var joinedMessage = serviceProvider.GetRequiredService <ChunkConsumer>().JoinIfComplete(chunk);

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

            var deserializedJoinedMessage = message.Endpoint.Serializer.Deserialize(joinedMessage);

            return(InboundMessageHelper.CreateNewInboundMessage(deserializedJoinedMessage, message));
        }
        protected override ErrorAction ApplyPolicy(IInboundMessage message, Exception exception)
        {
            _messageLogger.LogInformation(_logger, $"The message will be  be moved to '{_endpoint.Name}'.", message);

            if (message is IInboundBatch inboundBatch)
            {
                foreach (var singleFailedMessage in inboundBatch.Messages)
                {
                    PublishToNewEndpoint(singleFailedMessage, exception);
                }
            }
            else
            {
                PublishToNewEndpoint(message, exception);
            }

            return(ErrorAction.Skip);
        }
示例#31
0
        public static IInboundMessage <TMessage> CreateNewInboundMessage <TMessage>(TMessage message,
                                                                                    IInboundMessage sourceInboundMessage)
        {
            var newMessage = (InboundMessage)Activator.CreateInstance(typeof(InboundMessage <>).MakeGenericType(message.GetType()));

            if (sourceInboundMessage.Headers != null)
            {
                newMessage.Headers.AddRange(sourceInboundMessage.Headers);
            }

            newMessage.Message        = message;
            newMessage.Endpoint       = sourceInboundMessage.Endpoint;
            newMessage.Offset         = sourceInboundMessage.Offset;
            newMessage.FailedAttempts = sourceInboundMessage.FailedAttempts;
            newMessage.MustUnwrap     = sourceInboundMessage.MustUnwrap;

            return((IInboundMessage <TMessage>)newMessage);
        }
示例#32
0
        messages.All(msg => CanHandle(msg, exception));     // TODO: Check this

        public virtual bool CanHandle(IInboundMessage message, Exception exception)
        {
            if (message == null)
            {
                _logger.LogTrace($"The policy '{GetType().Name}' cannot be applied because the message is null.");
                return(false);
            }

            var failedAttempts = message.Headers.GetValueOrDefault <int>(MessageHeader.FailedAttemptsKey);

            if (MaxFailedAttemptsSetting >= 0 && failedAttempts > MaxFailedAttemptsSetting)
            {
                _messageLogger.LogTrace(_logger, $"The policy '{GetType().Name}' will be skipped because the current failed attempts " +
                                        $"({failedAttempts}) exceeds the configured maximum attempts " +
                                        $"({MaxFailedAttemptsSetting}).", message);

                return(false);
            }

            if (_includedExceptions.Any() && _includedExceptions.All(e => !e.IsInstanceOfType(exception)))
            {
                _messageLogger.LogTrace(_logger, $"The policy '{GetType().Name}' will be skipped because the {exception.GetType().Name} " +
                                        "is not in the list of handled exceptions.", message);

                return(false);
            }

            if (_excludedExceptions.Any(e => e.IsInstanceOfType(exception)))
            {
                _messageLogger.LogTrace(_logger, $"The policy '{GetType().Name}' will be skipped because the {exception.GetType().Name} " +
                                        "is in the list of excluded exceptions.", message);

                return(false);
            }

            if (_applyRule != null && !_applyRule.Invoke(message, exception))
            {
                _messageLogger.LogTrace(_logger, $"The policy '{GetType().Name}' will be skipped because the apply rule has been " +
                                        "evaluated and returned false.", message);
                return(false);
            }

            return(true);
        }
        private static IInboundMessage DeserializeIfNeeded(IInboundMessage message)
        {
            if (message is IInboundBatch batch)
            {
                return(new InboundBatch(
                           batch.Id,
                           batch.Messages.Select(DeserializeIfNeeded),
                           batch.Endpoint));
            }

            if (message.Message is byte[])
            {
                return(InboundMessageHelper.CreateNewInboundMessage(
                           Deserialize(message),
                           message));
            }

            return(message);
        }