Пример #1
0
        public TSaga Find <TSaga>(Guid correlationId) where TSaga : class
        {
            string dataSerialised;

            if (!DataDictionary.TryGetValue(correlationId, out dataSerialised))
            {
                return(null);
            }

            string headersSerialised;
            var    headers = new Dictionary <String, String>();

            if (HeadersDictionary.TryGetValue(correlationId, out headersSerialised))
            {
                headers = messageSerialiser.Deserialise <Dictionary <String, String> >(headersSerialised);
            }

            var sagaDataType = Reflection.GetInterfaceGenericType <TSaga>(typeof(ISaga <>));

            var dataObject = messageSerialiser.Deserialise(dataSerialised, sagaDataType);

            var saga = serviceLocator.Resolve <TSaga>();

            Reflection.Set(saga, "SagaData", dataObject);
            Reflection.Set(saga, "CorrelationId", correlationId);
            Reflection.Set(saga, "Headers", headers);

            return(saga);
        }
Пример #2
0
        public async Task <MessageHandlingResult> ProcessMessageAsync(
            Message message, IEndpointHandlingConfig handlingConfig, CancellationToken ct)
        {
            try
            {
                var messageContext = MessageContext.Create(message);

                var contractMessage = _serialiser.Deserialise <TMessage>(message);
                if (contractMessage == null)
                {
                    return(MessageHandlingResult.UnrecognisedMessageType(
                               $"Serialiser could not de-serialise message to {typeof(TMessage).AssemblyQualifiedName}",
                               message.UserProperties));
                }

                var stopwatch      = Stopwatch.StartNew();
                var handlingResult = await _handler.HandleMessageAsync(contractMessage, messageContext, ct).ConfigureAwait(false);

                _instrumentor.TrackElapsed(
                    LogEventIds.HandlerMeasuredElapsed, stopwatch.ElapsedMilliseconds, _handler.GetType().Name, message.UserProperties);

                return(handlingResult);
            }
            catch (OperationCanceledException ex)
            {
                _logger.LogWarning(LogEventIds.ProcessorCancelled, ex, $"Operation was cancelled in Processor<{typeof(TMessage).Name}>");
                return(MessageHandlingResult.Abandoned(ex, message.UserProperties));
            }
        }
Пример #3
0
        /// <summary>
        /// After the saga is initialised but before it is saved to the storage: save the message currently in the pipeline into Saga.Headers
        /// </summary>
        /// <param name="context">Context containing objects and data related to the operation</param>
        public override void AfterInitialisation(PipelineContext context)
        {
            var    sagaMetadata = new SagaMetadata();
            String serialisedMetadata;

            if (context.AccessibleSaga.Headers.TryGetValue(MetadataKeyName, out serialisedMetadata))
            {
                sagaMetadata = serialiser.Deserialise <SagaMetadata>(serialisedMetadata);
            }

            sagaMetadata.DateCreated      = TimeProvider.Current.UtcNow;
            sagaMetadata.DateLastModified = TimeProvider.Current.UtcNow;
            sagaMetadata.ReceivedMessages.Add(new ReceivedMessage(context.Message, context.OperationResult));

            context.AccessibleSaga.Headers[MetadataKeyName] = serialiser.Serialise(sagaMetadata);
        }
Пример #4
0
        /// <summary>
        /// Finds and returns saga instance with the given correlation ID.
        /// You will get exceptions if TSaga does not match the actual saga data with the provided exception.
        ///
        /// Actually creates an instance of saga from service locator, retrieves SagaData and Headers from the storage and populates the instance with these.
        /// </summary>
        /// <typeparam name="TSaga">Type of saga we are looking for</typeparam>
        /// <param name="correlationId">CorrelationId to identify the saga</param>
        /// <returns>An instance of the saga. Or Null if there is no saga with this ID.</returns>
        public TSaga Find <TSaga>(Guid correlationId) where TSaga : class, IAccessibleSaga
        {
            Guard.ArgumentIsNotNull(correlationId, nameof(correlationId));

            using (var connection = connectionFactory.CreateOpenConnection())
                using (var database = new Database(connection))
                {
                    var sql           = Sql.Builder.Where("correlationId = @0", correlationId);
                    var persistedData = database.SingleOrDefault <SagaData>(sql);

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

                    var sagaInstance = sagaFactory.ResolveSaga <TSaga>();
                    var sagaDataType = NSagaReflection.GetInterfaceGenericType <TSaga>(typeof(ISaga <>));
                    var sagaData     = messageSerialiser.Deserialise(persistedData.BlobData, sagaDataType);

                    var headersSql       = Sql.Builder.Where("correlationId = @0", correlationId);
                    var headersPersisted = database.Query <SagaHeaders>(headersSql);
                    var headers          = headersPersisted.ToDictionary(k => k.Key, v => v.Value);

                    NSagaReflection.Set(sagaInstance, "CorrelationId", correlationId);
                    NSagaReflection.Set(sagaInstance, "SagaData", sagaData);
                    NSagaReflection.Set(sagaInstance, "Headers", headers);

                    return(sagaInstance);
                }
        }
Пример #5
0
        public TSaga Find <TSaga>(Guid correlationId) where TSaga : class
        {
            var sql           = Sql.Builder.Where("correlationId = @0", correlationId);
            var persistedData = database.SingleOrDefault <SagaData>(sql);

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


            var sagaInstance = serviceLocator.Resolve <TSaga>();
            var sagaDataType = Reflection.GetInterfaceGenericType <TSaga>(typeof(ISaga <>));
            var sagaData     = messageSerialiser.Deserialise(persistedData.BlobData, sagaDataType);

            var headersSql       = Sql.Builder.Where("correlationId = @0", correlationId);
            var headersPersisted = database.Query <SagaHeaders>(headersSql);
            var headers          = headersPersisted.ToDictionary(k => k.Key, v => v.Value);

            Reflection.Set(sagaInstance, "CorrelationId", correlationId);
            Reflection.Set(sagaInstance, "SagaData", sagaData);
            Reflection.Set(sagaInstance, "Headers", headers);

            return(sagaInstance);
        }
Пример #6
0
        /// <summary>
        /// Listens for incoming messages on the <see cref="NetworkStream" />.
        /// Fires a <see cref="MessageReceived" /> event when a new <see cref="IMessage" /> has been received.
        /// </summary>
        /// <param name="clientUserId">The Id of the user the NetworkStream is linked to.</param>
        /// <param name="tcpClient">The stream between the Client and the Server.</param>
        public void ReceiveMessages(int clientUserId, TcpClient tcpClient)
        {
            using (NetworkStream networkStream = tcpClient.GetStream())
            {
                try
                {
                    while (true)
                    {
                        MessageIdentifier messageIdentifier = MessageIdentifierSerialiser.DeserialiseMessageIdentifier(networkStream);

                        IMessageSerialiser serialiser = SerialiserFactory.GetSerialiser(messageIdentifier);

                        IMessage message = serialiser.Deserialise(networkStream);

                        OnMessageReceived(new MessageEventArgs(message));
                    }
                }
                catch (IOException)
                {
                    Log.Info("Detected client disconnection, notifying Server of ClientDisconnection.");
                    IMessage message = new ClientDisconnection(clientUserId);

                    OnMessageReceived(new MessageEventArgs(message));
                }
            }
        }
Пример #7
0
        private IMessage GetConnectionIMessage()
        {
            MessageIdentifier messageIdentifier = MessageIdentifierSerialiser.DeserialiseMessageIdentifier(serverConnection.GetStream());

            IMessageSerialiser serialiser = SerialiserFactory.GetSerialiser(messageIdentifier);

            return(serialiser.Deserialise(serverConnection.GetStream()));
        }
        public void When_a_message_is_available_should_deserialise_and_return_requested_type_using_old_message_format()
        {
            messageRouter.Get("MyServiceDestination", out _).Returns("");
            serialiser.DeserialiseByStack("", "").Returns(c => throw new Exception());
            serialiser.Deserialise <IMetadataFile>("").Returns(new SuperMetadata());
            var result = messaging.TryStartMessage <IMetadataFile>("MyServiceDestination");

            Assert.That(result, Is.InstanceOf <IPendingMessage <IMetadataFile> >());
        }
Пример #9
0
        /// <summary>
        /// Poll for a waiting message. Returns default(T) if no message.
        /// <para></para>
        /// IMPORTANT: this will immediately remove the message from the broker queue.
        /// Use this only for non-critical transient messages.
        /// <para></para>
        /// For important messages, use `TryStartMessage`
        /// </summary>
        public T GetMessage <T>(string destinationName)
        {
            var messageString = messageRouter.GetAndFinish(destinationName, out var properties);

            if (messageString == null)
            {
                return(default(T));
            }

            try
            {
                return((T)serialiser.DeserialiseByStack(messageString, properties.OriginalType));
            }
            catch
            {
                return(serialiser.Deserialise <T>(messageString));
            }
        }
Пример #10
0
        public async Task DeQueueAsync(
            IMessage message,
            IEnumerable <MessageRegistration> messageRegistrations)
        {
            if (message is IPreparedMessage preparedMessage)
            {
                if (await _dataProtector.UnprotectAsync <Guid>(preparedMessage.SecurityToken, SharedDataKeys.Queue) != preparedMessage.Id)
                {
                    throw new BusinessApplicationException(ExceptionType.Unknown, "Unable to verify sender of message");
                }

                string unprotectedMessage = await _dataProtector.UnprotectAsync <string>(preparedMessage.Payload, SharedDataKeys.Queue);

                IMessage deserialisedMessage = _messageSerialiser.Deserialise(unprotectedMessage);

                using (_serviceProvider.CreateScope())
                {
                    using (ITransaction transaction = _transactionManager.Create())
                    {
                        try
                        {
                            foreach (MessageRegistration messageRegistration in messageRegistrations)
                            {
                                await(Task) messageRegistration.AsyncHandler.DynamicInvoke(deserialisedMessage);

                                transaction.Commit();
                            }
                        }
                        catch (Exception e)
                        {
                            throw new BusinessApplicationException(ExceptionType.Unknown, $"Unable to dequeue message for type: {message.Type}", e);
                        }
                    }

                    using (ITransaction transaction = _transactionManager.Create())
                    {
                        try
                        {
                            _messageDispatcher = _serviceProvider.GetRequiredService <IMessageDispatcher>();

                            await _messageDispatcher.DispatchMessagesAsync();

                            transaction.Commit();
                        }
                        catch (Exception e)
                        {
                            throw new BusinessApplicationException(ExceptionType.Unknown, $"Unable to forward messages for type: {message.Type}", e);
                        }
                    }
                }
            }
            else
            {
                throw new BusinessApplicationException(ExceptionType.Unknown, "Unable to verify sender of message");
            }
        }
Пример #11
0
        private static LoginRequest GetLoginRequest(TcpClient tcpClient)
        {
            MessageIdentifier messageIdentifier = MessageIdentifierSerialiser.DeserialiseMessageIdentifier(tcpClient.GetStream());

            IMessageSerialiser serialiser = SerialiserFactory.GetSerialiser(messageIdentifier);

            var loginRequest = (LoginRequest)serialiser.Deserialise(tcpClient.GetStream());

            return(loginRequest);
        }
Пример #12
0
        /// <summary>
        /// Gets the saga metadata from previous operations
        /// </summary>
        /// <param name="accessibleSaga">The accessible saga.</param>
        /// <param name="messageSerialiser">The message serialiser.</param>
        /// <returns></returns>
        public static SagaMetadata GetSagaMetadata(this IAccessibleSaga accessibleSaga, IMessageSerialiser messageSerialiser)
        {
            String serialisedMetadata;

            if (!accessibleSaga.Headers.TryGetValue(MetadataPipelineHook.MetadataKeyName, out serialisedMetadata))
            {
                return(null);
            }

            var metadata = messageSerialiser.Deserialise <SagaMetadata>(serialisedMetadata);

            return(metadata);
        }
Пример #13
0
        protected override void Given()
        {
            Sqs                   = Substitute.For <IAmazonSQS>();
            Serialiser            = Substitute.For <IMessageSerialiser>();
            SerialisationRegister = Substitute.For <IMessageSerialisationRegister>();
            Monitor               = Substitute.For <IMessageMonitor>();
            Handler               = Substitute.For <IHandler <GenericMessage> >();
            var response = GenerateResponseMessage(_messageTypeString, Guid.NewGuid());

            Sqs.ReceiveMessage(Arg.Any <ReceiveMessageRequest>()).Returns(x => response, x => new ReceiveMessageResponse());

            SerialisationRegister.GeTypeSerialiser(_messageTypeString).Returns(new TypeSerialiser(typeof(GenericMessage), Serialiser));
            DeserialisedMessage = new GenericMessage {
                RaisingComponent = "Component"
            };
            Serialiser.Deserialise(Arg.Any <string>(), typeof(GenericMessage)).Returns(x => DeserialisedMessage);
        }
        private async Task ProcessMessageAsync(
            string messageName,
            string serialisedMessage)
        {
            if (!_messageBusRegistrationsManager.HasRegistrationsForMessage(messageName))
            {
                return;
            }

            try
            {
                IEnumerable <MessageRegistration> registrations = _messageBusRegistrationsManager.GetRegistrationsForMessage(messageName);
                await _messageDeQueuer.DeQueueAsync(_messageSerialiser.Deserialise(serialisedMessage), registrations);
            }
            catch (Exception e)
            {
                _logger.LogCritical(e.Message);
            }
        }
Пример #15
0
        /// <summary>
        /// Finds and returns saga instance with the given correlation ID.
        /// You will get exceptions if TSaga does not match the actual saga data with the provided exception.
        ///
        /// Actually creates an instance of saga from service locator, retrieves SagaData and Headers from the storage and populates the instance with these.
        /// </summary>
        /// <typeparam name="TSaga">Type of saga we are looking for</typeparam>
        /// <param name="correlationId">CorrelationId to identify the saga</param>
        /// <returns>An instance of the saga. Or Null if there is no saga with this ID.</returns>
        public TSaga Find <TSaga>(Guid correlationId) where TSaga : class, IAccessibleSaga
        {
            Guard.ArgumentIsNotNull(correlationId, nameof(correlationId));

            var persistedData = database.GetById <SagaData>(correlationId).FirstOrDefault();

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

            var sagaInstance = sagaFactory.ResolveSaga <TSaga>();
            var sagaDataType = NSagaReflection.GetInterfaceGenericType <TSaga>(typeof(ISaga <>));
            var sagaData     = messageSerialiser.Deserialise(persistedData.BlobData, sagaDataType);

            var headersPersisted = database.GetById <SagaHeaders>(correlationId);
            var headers          = headersPersisted.ToDictionary(k => k.Key, v => v.Value);

            sagaInstance.CorrelationId = correlationId;
            sagaInstance.Headers       = headers;
            NSagaReflection.Set(sagaInstance, "SagaData", sagaData);

            return(sagaInstance);
        }
        public void Should_deserialise_to_a_concrete_implementation_of_the_requested_interface()
        {
            var result = subject.Deserialise <IMetadataFile>(message);

            Assert.That(result, Is.InstanceOf <IMetadataFile>());
        }