コード例 #1
0
        public void Should_set_label_when_convention_configured()
        {
            var queueName = "labelTest";
            var path = $@"{RuntimeEnvironment.MachineName}\private$\{queueName}";
            try
            {
                MsmqHelpers.DeleteQueue(path);
                MsmqHelpers.CreateQueue(path);
                var messageSender = new MsmqMessageDispatcher(new MsmqSettings(), _ => "mylabel");

                var bytes = new byte[]
                {
                    1
                };
                var headers = new Dictionary<string, string>();
                var outgoingMessage = new OutgoingMessage("1", headers, bytes);
                var transportOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(queueName), DispatchConsistency.Default);
                messageSender.Dispatch(new TransportOperations(transportOperation), new TransportTransaction(), new ContextBag());
                var messageLabel = ReadMessageLabel(path);
                Assert.AreEqual("mylabel", messageLabel);

            }
            finally
            {
                MsmqHelpers.DeleteQueue(path);
            }
        }
コード例 #2
0
        public void Should_split_multicast_and_unicast_messages()
        {
            var unicastOperation = new TransportOperation(CreateUniqueMessage(), new UnicastAddressTag("destination"), DispatchConsistency.Isolated);
            var multicastOperation = new TransportOperation(CreateUniqueMessage(), new MulticastAddressTag(typeof(object)), DispatchConsistency.Default);
            var operations = new[]
            {
                unicastOperation,
                multicastOperation
            };

            var result = new TransportOperations(operations);

            Assert.AreEqual(1, result.MulticastTransportOperations.Count());
            var multicastOp = result.MulticastTransportOperations.Single();
            Assert.AreEqual(multicastOperation.Message, multicastOp.Message);
            Assert.AreEqual((multicastOperation.AddressTag as MulticastAddressTag)?.MessageType, multicastOp.MessageType);
            Assert.AreEqual(multicastOperation.DeliveryConstraints, multicastOp.DeliveryConstraints);
            Assert.AreEqual(multicastOperation.RequiredDispatchConsistency, multicastOp.RequiredDispatchConsistency);

            Assert.AreEqual(1, result.UnicastTransportOperations.Count());
            var unicastOp = result.UnicastTransportOperations.Single();
            Assert.AreEqual(unicastOperation.Message, unicastOp.Message);
            Assert.AreEqual((unicastOperation.AddressTag as UnicastAddressTag)?.Destination, unicastOp.Destination);
            Assert.AreEqual(unicastOperation.DeliveryConstraints, unicastOp.DeliveryConstraints);
            Assert.AreEqual(unicastOperation.RequiredDispatchConsistency, unicastOp.RequiredDispatchConsistency);
        }
コード例 #3
0
        public void Should_use_string_empty_label_when_no_convention_configured()
        {
            var queueName = "emptyLabelTest";
            var path = $@".\private$\{queueName}";
            try
            {
                MsmqHelpers.DeleteQueue(path);
                MsmqHelpers.CreateQueue(path);
                var messageSender = new MsmqMessageDispatcher(new MsmqSettings(), pairs => string.Empty);

                var bytes = new byte[]
                {
                    1
                };
                var headers = new Dictionary<string, string>();
                var outgoingMessage = new OutgoingMessage("1", headers, bytes);
                var transportOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(queueName), DispatchConsistency.Default);
                messageSender.Dispatch(new TransportOperations(transportOperation), new TransportTransaction(), new ContextBag());
                var messageLabel = ReadMessageLabel(path);
                Assert.IsEmpty(messageLabel);

            }
            finally
            {
                MsmqHelpers.DeleteQueue(path);
            }
        }
コード例 #4
0
        public async Task Invoke(MessageContext context)
        {
            var timeoutId = context.Headers["Timeout.Id"];

            var timeoutData = await persister.Peek(timeoutId, context.Context).ConfigureAwait(false);

            if (timeoutData == null)
            {
                return;
            }

            timeoutData.Headers[Headers.TimeSent] = DateTimeExtensions.ToWireFormattedString(DateTime.UtcNow);
            timeoutData.Headers["NServiceBus.RelatedToTimeoutId"] = timeoutData.Id;

            var outgoingMessage = new OutgoingMessage(context.MessageId, timeoutData.Headers, timeoutData.State);
            var transportOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(timeoutData.Destination), dispatchConsistency);
            await dispatcher.Dispatch(new TransportOperations(transportOperation), context.TransportTransaction, context.Context).ConfigureAwait(false);

            var timeoutRemoved = await persister.TryRemove(timeoutId, context.Context).ConfigureAwait(false);
            if (!timeoutRemoved)
            {
                // timeout was concurrently removed between Peek and TryRemove. Throw an exception to rollback the dispatched message if possible.
                throw new Exception($"timeout '{timeoutId}' was concurrently processed.");
            }
        }
コード例 #5
0
        /// <summary>
        /// Creates an instance of an <see cref="OutboxMessage" />.
        /// </summary>
        /// <param name="messageId">The message identifier of the incoming message.</param>
        /// <param name="operations">The outgoing transport operations to execute as part of this incoming message.</param>
        public OutboxMessage(string messageId, TransportOperation[] operations)
        {
            Guard.AgainstNullAndEmpty(nameof(messageId), messageId);
            Guard.AgainstNull(nameof(operations), operations);

            MessageId = messageId;
            TransportOperations = operations;
        }
コード例 #6
0
        public async Task Invoke(MessageContext context)
        {
            var sagaId = Guid.Empty;

            string sagaIdString;
            if (context.Headers.TryGetValue(Headers.SagaId, out sagaIdString))
            {
                sagaId = Guid.Parse(sagaIdString);
            }

            if (context.Headers.ContainsKey(TimeoutManagerHeaders.ClearTimeouts))
            {
                if (sagaId == Guid.Empty)
                {
                    throw new InvalidOperationException("Invalid saga id specified, clear timeouts is only supported for saga instances");
                }

                await persister.RemoveTimeoutBy(sagaId, context.Context).ConfigureAwait(false);
            }
            else
            {
                string expire;
                if (!context.Headers.TryGetValue(TimeoutManagerHeaders.Expire, out expire))
                {
                    throw new InvalidOperationException("Non timeout message arrived at the timeout manager, id:" + context.MessageId);
                }

                var destination = GetReplyToAddress(context);

                string routeExpiredTimeoutTo;
                if (context.Headers.TryGetValue(TimeoutManagerHeaders.RouteExpiredTimeoutTo, out routeExpiredTimeoutTo))
                {
                    destination = routeExpiredTimeoutTo;
                }

                var data = new TimeoutData
                {
                    Destination = destination,
                    SagaId = sagaId,
                    State = context.Body,
                    Time = DateTimeExtensions.ToUtcDateTime(expire),
                    Headers = context.Headers,
                    OwningTimeoutManager = owningTimeoutManager
                };

                if (data.Time.AddSeconds(-1) <= DateTime.UtcNow)
                {
                    var outgoingMessage = new OutgoingMessage(context.MessageId, data.Headers, data.State);
                    var transportOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(data.Destination));
                    await dispatcher.Dispatch(new TransportOperations(transportOperation), context.TransportTransaction, context.Context).ConfigureAwait(false);
                    return;
                }

                await persister.Add(data, context.Context).ConfigureAwait(false);

                poller.NewTimeoutRegistered(data.Time);
            }
        }
コード例 #7
0
        public void When_providing_unsupported_addressTag_should_throw()
        {
            var transportOperation = new TransportOperation(
                CreateUniqueMessage(),
                new CustomAddressTag(), 
                DispatchConsistency.Default);

            Assert.Throws<ArgumentException>(() => new TransportOperations(transportOperation));
        }
コード例 #8
0
        public async Task RawSending()
        {
            IDispatchMessages dispatcher = null;

            #region DispatcherRawSending

            var headers = new Dictionary<string, string>();
            var outgoingMessage = new OutgoingMessage("MessageId", headers, new byte[] { });
            var constraints = new[] { new NonDurableDelivery() };
            UnicastAddressTag address = new UnicastAddressTag("Destination");
            var options = new DispatchOptions(address, DispatchConsistency.Default, constraints);
            TransportOperation transportOperation = new TransportOperation(outgoingMessage, options);
            await dispatcher.Dispatch(new[] { transportOperation }, new ContextBag());

            #endregion
        }
コード例 #9
0
        Task SendReadyMessage(int capacity, bool isStarting, TransportTransaction transaction)
        {
            //we use the actual address to make sure that the worker inside the master node will check in correctly
            var readyMessage = ControlMessageFactory.Create(MessageIntentEnum.Send);

            readyMessage.Headers.Add(LegacyDistributorHeaders.WorkerCapacityAvailable, capacity.ToString());
            readyMessage.Headers.Add(LegacyDistributorHeaders.WorkerSessionId, workerSessionId);
            readyMessage.Headers.Add(Headers.ReplyToAddress, receiveAddress);

            if (isStarting)
            {
                readyMessage.Headers.Add(LegacyDistributorHeaders.WorkerStarting, bool.TrueString);
            }

            var transportOperation = new TransportOperation(readyMessage, new UnicastAddressTag(distributorControlAddress));
            return dispatcher.Dispatch(new TransportOperations(transportOperation), transaction, new ContextBag());
        }
コード例 #10
0
        async Task RawSending(IDispatchMessages dispatcher)
        {
            #region DispatcherRawSending

            Dictionary<string, string> headers = new Dictionary<string, string>();
            OutgoingMessage outgoingMessage = new OutgoingMessage("MessageId", headers, new byte[]
            {
            });
            NonDurableDelivery[] constraints =
            {
                new NonDurableDelivery()
            };
            UnicastAddressTag address = new UnicastAddressTag("Destination");
            TransportOperation transportOperation = new TransportOperation(outgoingMessage, address, DispatchConsistency.Default, constraints);
            TransportOperations operations = new TransportOperations(transportOperation);
            await dispatcher.Dispatch(operations, new ContextBag());

            #endregion
        }
コード例 #11
0
        public async Task <ErrorHandleResult> OnError(IErrorHandlingPolicyContext handlingContext, IDispatchMessages dispatcher)
        {
            await Task.Delay(1000);

            if (handlingContext.Error.ImmediateProcessingFailures < immediateRetries)
            {
                return(ErrorHandleResult.RetryRequired);
            }

            logger.Error("Error processing a message. Continuing in throttled mode.", handlingContext.Error.Exception);

            //Move to back of the queue.
            var incomingMessage = handlingContext.Error.Message;
            var message         = new OutgoingMessage(incomingMessage.MessageId, incomingMessage.Headers, incomingMessage.Body);
            var operation       = new TransportOperation(message, new UnicastAddressTag(inputQueue));

            await dispatcher.Dispatch(new TransportOperations(operation), handlingContext.Error.TransportTransaction, new ContextBag())
            .ConfigureAwait(false);

            return(ErrorHandleResult.Handled);
        }
コード例 #12
0
    public override Task Invoke(IIncomingPhysicalMessageContext context, Func <Task> next, Func <IDispatchContext, Task> fork)
    {
        string destination;

        if (context.Message.Headers.TryGetValue("$.store-and-forward.destination", out destination))
        {
            TransportOperation operation = new TransportOperation(
                new OutgoingMessage(context.MessageId, context.Message.Headers, context.Message.Body),
                new UnicastAddressTag(destination));
            return(fork(new DispatchContext(operation, context)));
        }
        if (context.Message.Headers.TryGetValue("$.store-and-forward.eventtype", out destination))
        {
            Type messageType             = Type.GetType(destination, true);
            TransportOperation operation = new TransportOperation(
                new OutgoingMessage(context.MessageId, context.Message.Headers, context.Message.Body),
                new MulticastAddressTag(messageType));
            return(fork(new DispatchContext(operation, context)));
        }
        return(next());
    }
コード例 #13
0
    async Task Send(Subscriber subscriber, string publisherEndpoint, string messageType, MessageIntentEnum intent, IRawEndpoint dispatcher, InterBridgeRoutingSettings forwarding)
    {
        if (publisherEndpoint == null)
        {
            throw new UnforwardableMessageException("Subscription message does not contain the 'NServiceBus.Bridge.DestinationEndpoint' header.");
        }

        var subscriptionMessage = ControlMessageFactory.Create(intent);

        subscriptionMessage.Headers[Headers.SubscriptionMessageType]    = messageType;
        subscriptionMessage.Headers[Headers.ReplyToAddress]             = dispatcher.TransportAddress;
        subscriptionMessage.Headers[Headers.SubscriberTransportAddress] = dispatcher.TransportAddress;
        subscriptionMessage.Headers[Headers.SubscriberEndpoint]         = dispatcher.EndpointName;
        subscriptionMessage.Headers[Headers.TimeSent]           = DateTimeExtensions.ToWireFormattedString(DateTime.UtcNow);
        subscriptionMessage.Headers[Headers.NServiceBusVersion] = "6.3.1"; //The code has been copied from 6.3.1

        var typeFullName = messageType.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).First();

        if (forwarding.PublisherTable.TryGetValue(typeFullName, out var nextHopEndpoint))
        {
            subscriptionMessage.Headers["NServiceBus.Bridge.DestinationEndpoint"] = publisherEndpoint;
        }
        else
        {
            nextHopEndpoint = publisherEndpoint;
        }

        var publisherInstances = endpointInstances.FindInstances(nextHopEndpoint);
        var publisherAddresses = publisherInstances.Select(i => dispatcher.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i))).ToArray();

        foreach (var publisherAddress in publisherAddresses)
        {
            Logger.Debug(
                $"Sending {intent} request for {messageType} to {publisherAddress} on behalf of {subscriber.TransportAddress}.");

            var transportOperation = new TransportOperation(subscriptionMessage, new UnicastAddressTag(publisherAddress));
            await dispatcher.Dispatch(new TransportOperations(transportOperation), new TransportTransaction(),
                                      new ContextBag()).ConfigureAwait(false);
        }
    }
        public void Should_not_batch_transport_operations_of_the_same_type_with_different_dispatch_consistency()
        {
            var headers             = new Dictionary <string, string>();
            var body                = new byte[0];
            var deliveryConstraints = new List <DeliveryConstraint>();

            var operation1 = new TransportOperation(new OutgoingMessage("id-1", headers, body), new MulticastAddressTag(typeof(EventA)), DispatchConsistency.Default, deliveryConstraints);
            var operation2 = new TransportOperation(new OutgoingMessage("id-2", headers, body), new MulticastAddressTag(typeof(EventA)), DispatchConsistency.Isolated, deliveryConstraints);
            var operation3 = new TransportOperation(new OutgoingMessage("id-3", headers, body), new UnicastAddressTag("CommandA"), DispatchConsistency.Default, deliveryConstraints);
            var operation4 = new TransportOperation(new OutgoingMessage("id-4", headers, body), new UnicastAddressTag("CommandA"), DispatchConsistency.Isolated, deliveryConstraints);

            var transportOperations = new TransportOperations(operation1, operation2, operation3, operation4);

            var batcher = new Batcher(new FakeTopolySectionManager(), 5, "dummy");
            var batches = batcher.ToBatches(transportOperations);

            Assert.That(batches.Count, Is.EqualTo(4));
            Assert.That(batches[0].Operations.First().Message.MessageId, Is.EqualTo("id-1"));
            Assert.That(batches[1].Operations.First().Message.MessageId, Is.EqualTo("id-2"));
            Assert.That(batches[2].Operations.First().Message.MessageId, Is.EqualTo("id-3"));
            Assert.That(batches[3].Operations.First().Message.MessageId, Is.EqualTo("id-4"));
        }
コード例 #15
0
ファイル: Usage.cs プロジェクト: scrooby/docs.particular.net
    static async Task Start()
    {
        #region Configuration

        var senderConfig = RawEndpointConfiguration.Create(
            endpointName: "EndpointName",
            onMessage: OnMessage,
            poisonMessageQueue: "error");
        senderConfig.UseTransport <MsmqTransport>();

        var sender = await RawEndpoint.Start(senderConfig)
                     .ConfigureAwait(false);

        #endregion

        #region Sending

        var body    = Serialize();
        var headers = new Dictionary <string, string>
        {
            ["SomeHeader"] = "SomeValue"
        };
        var request = new OutgoingMessage(
            messageId: Guid.NewGuid().ToString(),
            headers: headers,
            body: body);

        var operation = new TransportOperation(
            request,
            new UnicastAddressTag("Receiver"));

        await sender.SendRaw(
            outgoingMessages : new TransportOperations(operation),
            transaction : new TransportTransaction(),
            context : new ContextBag())
        .ConfigureAwait(false);

        #endregion
    }
コード例 #16
0
        public async Task <bool> Handle(MessageContext context)
        {
            context.Headers.TryGetValue(ForwardHeader, out var forwardDestination);
            if (forwardDestination == null)
            {
                //This is not a delayed message. Process in local endpoint instance.
                return(false);
            }
            if (forwardDestination == localAddress)
            {
                context.Headers.Remove(ForwardHeader);
                //Do not forward the message. Process in local endpoint instance.
                return(false);
            }
            var outgoingMessage    = new OutgoingMessage(context.MessageId, context.Headers, context.Body);
            var transportOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(forwardDestination));

            context.Headers.Remove(ForwardHeader);
            await dispatcher.Dispatch(new TransportOperations(transportOperation), context.TransportTransaction, context.Extensions).ConfigureAwait(false);

            return(true);
        }
コード例 #17
0
        public async Task Start(IMessageDispatcher dispatcher, CancellationToken cancellationToken = default)
        {
            messageSender = dispatcher;
            try
            {
                // In order to verify if the queue exists, we are sending a control message to SC.
                // If we are unable to send a message because the queue doesn't exist, then we can fail fast.
                // We currently don't have a way to check if Queue exists in a transport agnostic way,
                // hence the send.
                var outgoingMessage = ControlMessageFactory.Create(MessageIntentEnum.Send);
                outgoingMessage.Headers[Headers.ReplyToAddress] = localAddress;
                var operation = new TransportOperation(outgoingMessage, new UnicastAddressTag(destinationQueue));
                await messageSender.Dispatch(new TransportOperations(operation), new TransportTransaction(), cancellationToken).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                const string errMsg = @"You have enabled saga state change auditing in your endpoint, however, this endpoint is unable to contact the ServiceControl to report endpoint information.
Please ensure that the specified queue is correct.";

                throw new Exception(errMsg, ex);
            }
        }
        static async Task <Message> DispatchMessage(string queueName, MsmqTransport settings = null, DispatchProperties dispatchProperties = null, CancellationToken cancellationToken = default)
        {
            if (settings == null)
            {
                settings = new MsmqTransport();
            }

            var path = $@".\private$\{queueName}";

            try
            {
                MsmqHelpers.DeleteQueue(path);
                MsmqHelpers.CreateQueue(path);

                var messageSender = new MsmqMessageDispatcher(settings, "timeouts");

                var bytes = new byte[]
                {
                    1
                };
                var headers         = new Dictionary <string, string>();
                var outgoingMessage = new OutgoingMessage("1", headers, bytes);

                dispatchProperties = dispatchProperties ?? new DispatchProperties();
                var transportOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(queueName), dispatchProperties);

                await messageSender.Dispatch(new TransportOperations(transportOperation), new TransportTransaction(), cancellationToken);

                using (var queue = new MessageQueue(path))
                    using (var message = queue.Receive(TimeSpan.FromSeconds(5)))
                    {
                        return(message);
                    }
            }
            finally
            {
                MsmqHelpers.DeleteQueue(path);
            }
        }
コード例 #19
0
        public void Should_batch_transport_operations_of_the_same_type_with_the_same_dispatch_consistency()
        {
            var headers             = new Dictionary <string, string>();
            var body                = new byte[0];
            var deliveryConstraints = new List <DeliveryConstraint>();

            var operation1 = new TransportOperation(new OutgoingMessage("id-1", headers, body), new MulticastAddressTag(typeof(EventA)), DispatchConsistency.Default, deliveryConstraints);
            var operation2 = new TransportOperation(new OutgoingMessage("id-2", headers, body), new MulticastAddressTag(typeof(EventA)), DispatchConsistency.Default, deliveryConstraints);
            var operation3 = new TransportOperation(new OutgoingMessage("id-3", headers, body), new UnicastAddressTag("CommandA"), DispatchConsistency.Isolated, deliveryConstraints);
            var operation4 = new TransportOperation(new OutgoingMessage("id-4", headers, body), new UnicastAddressTag("CommandA"), DispatchConsistency.Isolated);

            var transportOperations = new TransportOperations(operation1, operation2, operation3, operation4);

            var settings = new DefaultConfigurationValues().Apply(new SettingsHolder());

            var batcher = new Batcher(new FakeTopolySectionManager(), settings);
            var batches = batcher.ToBatches(transportOperations);

            Assert.That(batches.Count, Is.EqualTo(2));
            Assert.That(batches[0].Operations.Count, Is.EqualTo(2));
            Assert.That(batches[1].Operations.Count, Is.EqualTo(2));
        }
コード例 #20
0
        public void Should_calculate_size_of_each_batched_operation()
        {
            var headers = new Dictionary <string, string> {
                { "header", "value" }
            };
            var body = new byte[100];
            var deliveryConstraints = new List <DeliveryConstraint>();

            var operation1 = new TransportOperation(new OutgoingMessage("id-1", headers, body), new MulticastAddressTag(typeof(EventA)), DispatchConsistency.Default, deliveryConstraints);
            var operation2 = new TransportOperation(new OutgoingMessage("id-2", headers, body), new UnicastAddressTag("CommandA"), DispatchConsistency.Default, deliveryConstraints);

            var transportOperations = new TransportOperations(operation1, operation2);

            var settings = new DefaultConfigurationValues().Apply(new SettingsHolder());

            var batcher = new Batcher(new FakeTopolySectionManager(), settings);
            var batches = batcher.ToBatches(transportOperations);

            Assert.That(batches.Count, Is.EqualTo(2));
            Assert.That(batches[0].Operations.First().GetEstimatedSize(), Is.EqualTo(2088), "For default message size padding of 5% size should be 2,088 bytes");
            Assert.That(batches[1].Operations.First().GetEstimatedSize(), Is.EqualTo(2088), "For default message size padding of 5% size should be 2,088 bytes");
        }
コード例 #21
0
        Task Send(byte[] body, string messageType, TimeSpan timeToBeReceived, IMessageDispatcher dispatcher, CancellationToken cancellationToken)
        {
            var headers = new Dictionary <string, string>
            {
                [Headers.EnclosedMessageTypes] = messageType,
                [Headers.ContentType]          = ContentTypes.Json,
                [Headers.MessageIntent]        = sendIntent
            };

            if (localAddress != null)
            {
                headers[Headers.ReplyToAddress] = localAddress;
            }

            var outgoingMessage = new OutgoingMessage(Guid.NewGuid().ToString(), headers, body);
            var properties      = new DispatchProperties {
                DiscardIfNotReceivedBefore = new DiscardIfNotReceivedBefore(timeToBeReceived)
            };
            var operation = new TransportOperation(outgoingMessage, new UnicastAddressTag(destinationQueue), properties);

            return(dispatcher.Dispatch(new TransportOperations(operation), new TransportTransaction(), cancellationToken));
        }
コード例 #22
0
        public async Task <ErrorHandleResult> OnError(IErrorHandlingPolicyContext handlingContext, IDispatchMessages dispatcher)
        {
            if (handlingContext.Error.Exception is UnforwardableMessageException)
            {
                //UnforwardableMessageException immediately triggers poison queue
                return(await poisonMessageHandling(handlingContext, dispatcher).ConfigureAwait(false));
            }
            if (handlingContext.Error.ImmediateProcessingFailures < immediateRetries)
            {
                return(ErrorHandleResult.RetryRequired);
            }

            if (handlingContext.Error.DelayedDeliveriesPerformed >= delayedRetries)
            {
                //More than five times this message triggered throttled mode -> poison
                return(await poisonMessageHandling(handlingContext, dispatcher).ConfigureAwait(false));
            }

            //Move to back of the queue.
            var incomingMessage = handlingContext.Error.Message;
            var message         = new OutgoingMessage(incomingMessage.MessageId, incomingMessage.Headers, incomingMessage.Body);
            var operation       = new TransportOperation(message, new UnicastAddressTag(inputQueue));

            //Only increment the delayed retries count if CB was not armed. That means that at least one message was
            //successfully forwarded in between previous failure of this message and this failure.
            //This prevents prematurely exhausting delayed retries attempts without triggering the throttled mode
            if (!circuitBreaker.IsArmed && !(handlingContext.Error.Exception is ProcessCurrentMessageLaterException))
            {
                var newDelayedRetriesHeaderValue = handlingContext.Error.DelayedDeliveriesPerformed + 1;
                incomingMessage.Headers[Headers.DelayedRetries] = newDelayedRetriesHeaderValue.ToString();
            }
            await dispatcher.Dispatch(new TransportOperations(operation), handlingContext.Error.TransportTransaction, new ContextBag())
            .ConfigureAwait(false);

            //Notify the circuit breaker
            await circuitBreaker.Failure(handlingContext.Error.Exception).ConfigureAwait(false);

            return(ErrorHandleResult.Handled);
        }
コード例 #23
0
        /// <summary>
        /// Initialize one of the four transport operation machine types.  Both Pick-up machines have
        /// CanStop turned off because there are no circumstances where a Pick-up operation can be
        /// stopped, even though the TrayMover as a whole can be stopped during pick-up.  Both
        /// Drop-off machines have CanStop turned on initially so that either drop-off operation can
        /// be stopped.  If this TrayMover has already been stopped, then this will also
        /// stop a newly constructed CompleteDropoff machine before returning it.
        /// </summary>
        /// <param name="startingType"></param>
        /// <returns>TransportOperationMachine</returns>
        protected TransportOperationMachine InitializeSubmachine(TransportOperation startingType)
        {
            TransportOperationMachine initialized = null;

            lock (_subMachineLock)
            {
                switch (startingType)
                {
                case TransportOperation.BeginPickup:
                    BeginPickupMachine = CreateSubmachine("BeginTrayPickup", BeginPickupBuilder, _beginPickupConfig);
                    initialized        = BeginPickupMachine;
                    break;

                case TransportOperation.CompletePickup:
                    CompletePickupMachine = CreateSubmachine("CompleteTrayPickup", CompletePickupBuilder, _completePickupConfig);
                    initialized           = CompletePickupMachine;
                    break;

                case TransportOperation.BeginDropoff:
                    BeginDropoffMachine         = CreateSubmachine("BeginTrayDropoff", BeginDropoffBuilder, _beginDropoffConfig);
                    BeginDropoffMachine.CanStop = true;
                    initialized = BeginDropoffMachine;
                    break;

                case TransportOperation.CompleteDropoff:
                    CompleteDropoffMachine         = CreateSubmachine("CompleteTrayDropoff", CompleteDropoffBuilder, _completeDropoffConfig);
                    CompleteDropoffMachine.CanStop = true;
                    // CompleteDropoff needs to know if the mover was already stopped
                    if (IsStopped)
                    {
                        CompleteDropoffMachine.Stop();
                    }
                    initialized = CompleteDropoffMachine;
                    break;
                }
            }
            return(initialized);
        }
コード例 #24
0
        void SetupLegacyRetriesSatellite(FeatureConfigurationContext context)
        {
            var retriesQueueLogicalAddress   = context.Settings.LogicalAddress().CreateQualifiedAddress("Retries");
            var retriesQueueTransportAddress = context.Settings.GetTransportAddress(retriesQueueLogicalAddress);

            var mainQueueLogicalAddress   = context.Settings.LogicalAddress();
            var mainQueueTransportAddress = context.Settings.GetTransportAddress(mainQueueLogicalAddress);

            var requiredTransactionMode = context.Settings.GetRequiredTransactionModeForReceives();

            context.AddSatelliteReceiver("Legacy Retries Processor", retriesQueueTransportAddress, requiredTransactionMode, new PushRuntimeSettings(maxConcurrency: 1),
                                         (config, errorContext) =>
            {
                return(RecoverabilityAction.MoveToError(config.Failed.ErrorQueue));
            },
                                         (builder, messageContext) =>
            {
                var messageDispatcher = builder.Build <IDispatchMessages>();

                var outgoingHeaders = messageContext.Headers;
                outgoingHeaders.Remove("NServiceBus.ExceptionInfo.Reason");
                outgoingHeaders.Remove("NServiceBus.ExceptionInfo.ExceptionType");
                outgoingHeaders.Remove("NServiceBus.ExceptionInfo.InnerExceptionType");
                outgoingHeaders.Remove("NServiceBus.ExceptionInfo.HelpLink");
                outgoingHeaders.Remove("NServiceBus.ExceptionInfo.Message");
                outgoingHeaders.Remove("NServiceBus.ExceptionInfo.Source");
                outgoingHeaders.Remove("NServiceBus.FailedQ");
                outgoingHeaders.Remove("NServiceBus.TimeOfFailure");

                //HINT: this header is added by v3 when doing SLR
                outgoingHeaders.Remove("NServiceBus.OriginalId");

                var outgoingMessage   = new OutgoingMessage(messageContext.MessageId, outgoingHeaders, messageContext.Body);
                var outgoingOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(mainQueueTransportAddress));

                return(messageDispatcher.Dispatch(new TransportOperations(outgoingOperation), messageContext.TransportTransaction, messageContext.Extensions));
            });
        }
コード例 #25
0
        protected Task SendMessage(string address,
                                   Dictionary <string, string> headers           = null,
                                   TransportTransaction transportTransaction     = null,
                                   List <DeliveryConstraint> deliveryConstraints = null)
        {
            var messageId = Guid.NewGuid().ToString();
            var message   = new OutgoingMessage(messageId, headers ?? new Dictionary <string, string>(), new byte[0]);

            if (message.Headers.ContainsKey(TestIdHeaderName) == false)
            {
                message.Headers.Add(TestIdHeaderName, testId);
            }

            var dispatcher = lazyDispatcher.Value;

            if (transportTransaction == null)
            {
                transportTransaction = new TransportTransaction();
            }
            var transportOperation = new TransportOperation(message, new UnicastAddressTag(address), DispatchConsistency.Default, deliveryConstraints ?? new List <DeliveryConstraint>());

            return(dispatcher.Dispatch(new TransportOperations(transportOperation), transportTransaction, new ContextBag()));
        }
コード例 #26
0
        public async Task Should_filter_invalid_docid_character()
        {
            var persister = new OutboxPersister(store, testEndpointName, CreateTestSessionOpener());

            var guid                = Guid.NewGuid();
            var messageId           = $@"{guid}\12345";
            var emptyDictionary     = new Dictionary <string, string>();
            var operation           = new TransportOperation("test", emptyDictionary, new byte[0], emptyDictionary);
            var transportOperations = new [] { operation };

            using (var transaction = await persister.BeginTransaction(new ContextBag()))
            {
                await persister.Store(new OutboxMessage(messageId, transportOperations), transaction, new ContextBag());

                await transaction.Commit();
            }

            var outboxMessage = await persister.Get(messageId, new ContextBag());

            Assert.AreEqual(messageId, outboxMessage.MessageId);
            Assert.AreEqual(1, outboxMessage.TransportOperations.Length);
            Assert.AreEqual("test", outboxMessage.TransportOperations[0].MessageId);
        }
コード例 #27
0
        public void Invoke(OutgoingContext context, Action next)
        {
            OutboxMessage currentOutboxMessage;

            if (context.TryGet(out currentOutboxMessage))
            {
                var options            = context.DeliveryOptions.ToTransportOperationOptions();
                var transportOperation = new TransportOperation(context.OutgoingMessage.Id, options, context.OutgoingMessage.Body, context.OutgoingMessage.Headers);

                if (context.OutgoingMessage.TimeToBeReceived != TimeSpan.MaxValue)
                {
                    options["TimeToBeReceived"] = context.OutgoingMessage.TimeToBeReceived.ToString();
                }

                currentOutboxMessage.TransportOperations.Add(transportOperation);
            }
            else
            {
                DispatchMessageToTransportBehavior.InvokeNative(context.DeliveryOptions, context.OutgoingMessage);

                next();
            }
        }
コード例 #28
0
        protected override async Task OnReceived(IRequest request, string connectionId, string data)
        {
            try
            {
                var jObject = JObject.Parse(data);

                var jsonMessage = jObject["message"].ToString();
                var messageType = jObject["type"].ToString();

                var message = new OutgoingMessage(Guid.NewGuid().ToString(), new Dictionary <string, string>
                {
                    { Headers.EnclosedMessageTypes, messageTypes[messageType] }
                }, Encoding.UTF8.GetBytes(jsonMessage));
                var transportOperation  = new TransportOperation(message, new UnicastAddressTag(localAddress));
                var transportOperations = new TransportOperations(transportOperation);

                await sender.Dispatch(transportOperations, transportTransaction, contextBag).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Log.Error($"Failed to process SignalR message. AuditMessage={data}", ex);
                throw;
            }
        }
コード例 #29
0
        async Task <ErrorHandleResult> OnError(ErrorContext errorContext, CancellationToken cancellationToken)
        {
            Log.Error($"OnError {errorContext.Message.MessageId}", errorContext.Exception);

            if (errorContext.ImmediateProcessingFailures < numberOfRetries)
            {
                return(ErrorHandleResult.RetryRequired);
            }

            var message = errorContext.Message;

            ExceptionHeaderHelper.SetExceptionHeaders(message.Headers, errorContext.Exception);
            message.Headers[FaultsHeaderKeys.FailedQ] = errorContext.ReceiveAddress;
            foreach (var pair in faultMetadata)
            {
                message.Headers[pair.Key] = pair.Value;
            }

            var outgoingMessage    = new OutgoingMessage(message.NativeMessageId, message.Headers, message.Body);
            var transportOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(errorQueue));
            await dispatcher.Dispatch(new TransportOperations(transportOperation), errorContext.TransportTransaction, cancellationToken).ConfigureAwait(false);

            return(ErrorHandleResult.Handled);
        }
コード例 #30
0
        public async Task RawSending()
        {
            IDispatchMessages dispatcher = null;

            #region DispatcherRawSending

            var headers         = new Dictionary <string, string>();
            var outgoingMessage = new OutgoingMessage("MessageId", headers, new byte[]
            {
            });
            var constraints = new[]
            {
                new NonDurableDelivery()
            };
            UnicastAddressTag         address                             = new UnicastAddressTag("Destination");
            TransportOperation        transportOperation                  = new TransportOperation(outgoingMessage, address, DispatchConsistency.Default, constraints);
            UnicastTransportOperation unicastTransportOperation           = new UnicastTransportOperation(outgoingMessage, "destination");
            IEnumerable <MulticastTransportOperation> multicastOperations = Enumerable.Empty <MulticastTransportOperation>();
            UnicastTransportOperation[] unicastOperations                 = { unicastTransportOperation };
            TransportOperations         operations                        = new TransportOperations(multicastOperations, unicastOperations);
            await dispatcher.Dispatch(operations, new ContextBag());

            #endregion
        }
コード例 #31
0
        async Task RawSending(IDispatchMessages dispatcher)
        {
            #region DispatcherRawSending

            var headers         = new Dictionary <string, string>();
            var outgoingMessage = new OutgoingMessage("MessageId", headers, new byte[]
            {
            });
            var constraints = new List <DeliveryConstraint>
            {
                new NonDurableDelivery()
            };
            var address   = new UnicastAddressTag("Destination");
            var operation = new TransportOperation(
                message: outgoingMessage,
                addressTag: address,
                requiredDispatchConsistency: DispatchConsistency.Default,
                deliveryConstraints: constraints);
            var operations = new TransportOperations(operation);
            await dispatcher.Dispatch(operations, new TransportTransaction(), new ContextBag())
            .ConfigureAwait(false);

            #endregion
        }
コード例 #32
0
        static async Task OnOutgoingMessage(MessageContext delayedMessage, IDispatchMessages dispatcher)
        {
            string dueHeader;
            string destination;
            var    headers = delayedMessage.Headers;

            if (!headers.TryGetValue("NServiceBus.Raw.DelayedRetries.Due", out dueHeader) ||
                !headers.TryGetValue("NServiceBus.Raw.DelayedRetries.RetryTo", out destination))
            {
                //Skip
                return;
            }
            var due       = DateTime.Parse(dueHeader).ToUniversalTime();
            var sleepTime = due - DateTime.UtcNow;

            if (sleepTime > TimeSpan.Zero)
            {
                await Task.Delay(sleepTime).ConfigureAwait(false);
            }

            var    attempt = 1;
            string delayedRetryHeader;

            if (delayedMessage.Headers.TryGetValue("NServiceBus.Raw.DelayedRetries.Attempt", out delayedRetryHeader))
            {
                attempt = int.Parse(delayedRetryHeader);
            }
            attempt++;
            headers.Remove("NServiceBus.Raw.DelayedRetries.Due");
            headers.Remove("NServiceBus.Raw.DelayedRetries.RetryTo");
            headers["NServiceBus.Raw.DelayedRetries.Attempt"] = attempt.ToString();

            var message   = new OutgoingMessage(delayedMessage.MessageId, headers, delayedMessage.Body);
            var operation = new TransportOperation(message, new UnicastAddressTag(destination));
            await dispatcher.Dispatch(new TransportOperations(operation), delayedMessage.TransportTransaction, delayedMessage.Extensions).ConfigureAwait(false);
        }
コード例 #33
0
ファイル: RawSend.cs プロジェクト: cdnico/docs.particular.net
        public async Task RawSending()
        {
            IDispatchMessages dispatcher = null;

            #region DispatcherRawSending

            var headers = new Dictionary<string, string>();
            var outgoingMessage = new OutgoingMessage("MessageId", headers, new byte[]
            {
            });
            var constraints = new[]
            {
                new NonDurableDelivery()
            };
            UnicastAddressTag address = new UnicastAddressTag("Destination");
            TransportOperation transportOperation = new TransportOperation(outgoingMessage, address, DispatchConsistency.Default, constraints);
            UnicastTransportOperation unicastTransportOperation = new UnicastTransportOperation(outgoingMessage, "destination");
            IEnumerable<MulticastTransportOperation> multicastOperations = Enumerable.Empty<MulticastTransportOperation>();
            UnicastTransportOperation[] unicastOperations = {unicastTransportOperation};
            TransportOperations operations = new TransportOperations(multicastOperations, unicastOperations);
            await dispatcher.Dispatch(operations, new ContextBag());

            #endregion
        }
コード例 #34
0
    Task Forward(MessageContext context, IRawEndpoint dispatcher, string destinationEndpoint, string sourcePort)
    {
        var forwardedHeaders = new Dictionary <string, string>(context.Headers);

        var address = SelectDestinationAddress(destinationEndpoint, i => dispatcher.ToTransportAddress(LogicalAddress.CreateRemoteAddress(i)));

        if (forwardedHeaders.TryGetValue(Headers.ReplyToAddress, out var replyToHeader) &&
            forwardedHeaders.TryGetValue(Headers.CorrelationId, out var correlationId))
        {
            // pipe-separated TLV format
            var newCorrelationId = $"id|{correlationId.Length}|{correlationId}|reply-to|{replyToHeader.Length}|{replyToHeader}";
            if (sourcePort != null)
            {
                newCorrelationId += $"|port|{sourcePort.Length}|{sourcePort}";
            }
            forwardedHeaders[Headers.CorrelationId] = newCorrelationId;
        }
        forwardedHeaders[Headers.ReplyToAddress] = dispatcher.TransportAddress;

        var outgoingMessage = new OutgoingMessage(context.MessageId, forwardedHeaders, context.Body);
        var operation       = new TransportOperation(outgoingMessage, new UnicastAddressTag(address));

        return(dispatcher.Dispatch(new TransportOperations(operation), context.TransportTransaction, context.Extensions));
    }
コード例 #35
0
ファイル: BusStuff.cs プロジェクト: kortov1337/CT
    public static Task Send(string servName, Operation op)
    {
        var body    = Serialize(op);
        var headers = new Dictionary <string, string>
        {
            ["Operation"] = op.OperationType,
            ["To"]        = "Subscriber1"
        };
        var request = new OutgoingMessage(
            messageId: Guid.NewGuid().ToString(),
            headers: headers,
            body: body);

        var operation = new TransportOperation(
            request,
            new UnicastAddressTag(servName));

        serverEndpoint.Dispatch(
            outgoingMessages: new TransportOperations(operation),
            transaction: new TransportTransaction(),
            context: new ContextBag())
        .ConfigureAwait(false);
        return(Task.CompletedTask);
    }
コード例 #36
0
    protected override async Task <bool> Terminate(ForwardReplyContext context)
    {
        string replyTo                = null;
        string replyToRouter          = null;
        string unwrappedCorrelationId = null;

        if (!context.ForwardedHeaders.TryGetValue(RouterHeaders.ReplyToTrace, out var correlationId))
        {
            throw new UnforwardableMessageException($"The reply has to contain a '{Headers.CorrelationId}' header set by the router connector when sending out the initial message.");
        }

        try
        {
            correlationId.DecodeTLV((t, v) =>
            {
                if (t == "reply-to")
                {
                    replyTo = v;
                }
                if (t == "id")
                {
                    unwrappedCorrelationId = v;
                }
                if (t == "reply-to-router")
                {
                    replyToRouter = v;
                }
            });
        }
        catch (Exception e)
        {
            throw new UnforwardableMessageException($"Cannot decode value in '{Headers.CorrelationId}' header: " + e.Message);
        }

        var outgoingMessage = new OutgoingMessage(context.MessageId, context.ForwardedHeaders, context.ReceivedBody);

        if (replyTo != null)
        {
            //Copy the correlation ID header which contains the route the reply underwent to previous header to preserve it
            context.ForwardedHeaders[RouterHeaders.ReplyToTrace] = context.ForwardedHeaders[Headers.CorrelationId];

            //Update the correlation ID
            context.ForwardedHeaders[Headers.CorrelationId] = unwrappedCorrelationId ?? correlationId;
            context.ForwardedHeaders.Remove(RouterHeaders.ReplyToRouter);

            var operation   = new TransportOperation(outgoingMessage, new UnicastAddressTag(replyTo));
            var chain       = context.Chains.Get <PostroutingContext>();
            var forkContext = new PostroutingContext(null, operation, context);
            await chain.Invoke(forkContext).ConfigureAwait(false);

            return(true);
        }
        if (replyToRouter != null)
        {
            context.ForwardedHeaders[RouterHeaders.ReplyToTrace] = unwrappedCorrelationId ?? correlationId;
            var chain       = context.Chains.Get <AnycastContext>();
            var forkContext = new AnycastContext(replyToRouter, outgoingMessage, DistributionStrategyScope.Send, context);

            await chain.Invoke(forkContext).ConfigureAwait(false);

            return(true);
        }

        throw new UnforwardableMessageException("The reply contains neither \'reply-to\' nor \'reply-to-router\' correlation parameters required to route the message.");
    }
コード例 #37
0
        /// <summary>
        /// Adds a range of transport operations.
        /// </summary>
        /// <param name="transportOperations">The transport operations to be added.</param>
        public void AddRange(TransportOperation[] transportOperations)
        {
            Guard.AgainstNullAndEmpty(nameof(transportOperations), transportOperations);

            operations.PushRange(transportOperations);
        }
コード例 #38
0
        /// <summary>
        /// Adds a transport operation.
        /// </summary>
        /// <param name="transportOperation">The transport operation to be added.</param>
        public void Add(TransportOperation transportOperation)
        {
            Guard.AgainstNull(nameof(transportOperation), transportOperation);

            operations.Push(transportOperation);
        }
コード例 #39
0
        public static async Task Main(string[] args)
        {
            var nhConfig = new Configuration();

            nhConfig.SetProperty(Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider");
            nhConfig.SetProperty(Environment.ConnectionDriver, "NHibernate.Driver.Sql2008ClientDriver");
            nhConfig.SetProperty(Environment.Dialect, "NHibernate.Dialect.MsSql2008Dialect");
            nhConfig.SetProperty(Environment.ConnectionString, System.Environment.GetEnvironmentVariable("SQLServerConnectionString"));

            var mapper = new ModelMapper();

            mapper.AddMapping <TimeoutEntityMap>();
            var mappings = mapper.CompileMappingForAllExplicitlyAddedEntities();

            nhConfig.AddMapping(mappings);

            var sessionFactory =
                nhConfig.BuildSessionFactory();

            var senderConfig = RawEndpointConfiguration.CreateSendOnly("DUMMY");
            var transport    = senderConfig.UseTransport <SqsTransport>();

            transport.UnrestrictedDurationDelayedDelivery();

            var sender = await RawEndpoint.Start(senderConfig)
                         .ConfigureAwait(false);

            var ignoreMachineName = true; // Must be true for Sqs
            var now = DateTime.UtcNow;

            using (var session = sessionFactory.OpenStatelessSession())
            {
                var timeoutEntities = await session.Query <TimeoutEntity>().Take(100).ToListAsync();

                var transportOperations = new List <TransportOperation>();

                foreach (var timeout in timeoutEntities)
                {
                    await Console.Out.WriteLineAsync($"Id:{timeout.Id} Time:{timeout.Time:s} Destination:{timeout.Destination} {timeout.Endpoint}").ConfigureAwait(false);

                    var body        = timeout.State;
                    var headers     = ConvertStringToDictionary(timeout.Headers);
                    var timestamp   = timeout.Time;
                    var destination = timeout.Destination;
                    var id          = headers["NServiceBus.MessageId"];

                    if (ignoreMachineName)
                    {
                        var at = destination.LastIndexOf("@", StringComparison.InvariantCulture);

                        if (at != -1)
                        {
                            destination = destination.Substring(0, at);
                        }
                    }

                    var age = now - timestamp;

                    var request = new OutgoingMessage(
                        messageId: timeout.Id.ToString(),
                        headers: headers,
                        body: body
                        );

                    var operation = new TransportOperation(
                        request,
                        new UnicastAddressTag(destination)
                        , DispatchConsistency.Default, new List <DeliveryConstraint>
                    {
                        new DoNotDeliverBefore(timestamp)
                    });

                    if (age.Ticks > 0)
                    {
                        await Console.Out.WriteLineAsync($"Warning: Message {id} was scheduled for {timestamp} which passed {age} ago.")
                        .ConfigureAwait(false);
                    }

                    transportOperations.Add(operation);
                }
                await sender.Dispatch(
                    outgoingMessages : new TransportOperations(transportOperations.ToArray()),
                    transaction : new TransportTransaction(),
                    context : new ContextBag()
                    )
                .ConfigureAwait(false);
            }
        }
コード例 #40
0
 /// <summary>
 /// Creates new instance.
 /// </summary>
 public PostroutingContext(string destinationEndpoint, TransportOperation message, RuleContext parent)
     : base(parent)
 {
     Messages            = new [] { message };
     DestinationEndpoint = destinationEndpoint;
 }
コード例 #41
0
        public void Proper_exception_is_thrown_if_queue_does_not_exist()
        {
            var operation = new TransportOperation(new OutgoingMessage("1", new Dictionary <string, string>(), new byte[0]), new UnicastAddressTag("InvalidQueue"));

            Assert.That(async() => await dispatcher.Dispatch(new TransportOperations(operation), new TransportTransaction()), Throws.TypeOf <QueueNotFoundException>());
        }
コード例 #42
0
 public DispatchContext(TransportOperation operation, IBehaviorContext parentContext)
     : base(parentContext?.Extensions)
 {
     this.operation = operation;
 }
コード例 #43
0
        void SetupLegacyRetriesSatellite(FeatureConfigurationContext context)
        {
            var retriesQueueLogicalAddress = context.Settings.LogicalAddress().CreateQualifiedAddress("Retries");
            var retriesQueueTransportAddress = context.Settings.GetTransportAddress(retriesQueueLogicalAddress);

            var mainQueueLogicalAddress = context.Settings.LogicalAddress();
            var mainQueueTransportAddress = context.Settings.GetTransportAddress(mainQueueLogicalAddress);

            var requiredTransactionMode = context.Settings.GetRequiredTransactionModeForReceives();

            context.AddSatelliteReceiver("Legacy Retries Processor", retriesQueueTransportAddress, requiredTransactionMode, new PushRuntimeSettings(maxConcurrency: 1),
                (config, errorContext) =>
                {
                    return RecoverabilityAction.MoveToError(config.Failed.ErrorQueue);
                },
                (builder, messageContext) =>
                {
                    var messageDispatcher = builder.Build<IDispatchMessages>();

                    var outgoingHeaders = messageContext.Headers;
                    outgoingHeaders.Remove("NServiceBus.ExceptionInfo.Reason");
                    outgoingHeaders.Remove("NServiceBus.ExceptionInfo.ExceptionType");
                    outgoingHeaders.Remove("NServiceBus.ExceptionInfo.InnerExceptionType");
                    outgoingHeaders.Remove("NServiceBus.ExceptionInfo.HelpLink");
                    outgoingHeaders.Remove("NServiceBus.ExceptionInfo.Message");
                    outgoingHeaders.Remove("NServiceBus.ExceptionInfo.Source");
                    outgoingHeaders.Remove("NServiceBus.FailedQ");
                    outgoingHeaders.Remove("NServiceBus.TimeOfFailure");

                    //HINT: this header is added by v3 when doing SLR
                    outgoingHeaders.Remove("NServiceBus.OriginalId");

                    var outgoingMessage = new OutgoingMessage(messageContext.MessageId, outgoingHeaders, messageContext.Body);
                    var outgoingOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(mainQueueTransportAddress));

                    return messageDispatcher.Dispatch(new TransportOperations(outgoingOperation), messageContext.TransportTransaction, messageContext.Context);
                });
        }
コード例 #44
0
        async Task <int> Stage(RetryBatch stagingBatch, IAsyncDocumentSession session)
        {
            var stagingId = Guid.NewGuid().ToString();

            var failedMessageRetryDocs = await session.LoadAsync <FailedMessageRetry>(stagingBatch.FailureRetries).ConfigureAwait(false);

            var failedMessageRetriesById = failedMessageRetryDocs
                                           .Where(r => r != null && r.RetryBatchId == stagingBatch.Id)
                                           .Distinct(FailedMessageEqualityComparer.Instance)
                                           .ToDictionary(x => x.FailedMessageId, x => x);

            foreach (var failedMessageRetry in failedMessageRetryDocs)
            {
                if (failedMessageRetry != null)
                {
                    session.Advanced.Evict(failedMessageRetry);
                }
            }

            if (failedMessageRetriesById.Count == 0)
            {
                Log.Info($"Retry batch {stagingBatch.Id} cancelled as all matching unresolved messages are already marked for retry as part of another batch.");
                session.Delete(stagingBatch);
                return(0);
            }

            var failedMessagesDocs = await session.LoadAsync <FailedMessage>(failedMessageRetriesById.Keys).ConfigureAwait(false);

            var messages = failedMessagesDocs.Where(m => m != null).ToArray();

            Log.Info($"Staging {messages.Length} messages for retry batch {stagingBatch.Id} with staging attempt Id {stagingId}.");

            var previousAttemptFailed = false;
            var transportOperations   = new TransportOperation[messages.Length];
            var current = 0;

            foreach (var failedMessage in messages)
            {
                transportOperations[current++] = ToTransportOperation(failedMessage, stagingId);

                if (!previousAttemptFailed)
                {
                    previousAttemptFailed = failedMessageRetriesById[failedMessage.Id].StageAttempts > 0;
                }

                // should not be done concurrently due to sessions not being thread safe
                failedMessage.Status = FailedMessageStatus.RetryIssued;
            }

            await TryDispatch(transportOperations, messages, failedMessageRetriesById, stagingId, previousAttemptFailed).ConfigureAwait(false);

            if (stagingBatch.RetryType != RetryType.FailureGroup) //FailureGroup published on completion of entire group
            {
                var failedIds = messages.Select(x => x.UniqueMessageId).ToArray();
                await domainEvents.Raise(new MessagesSubmittedForRetry
                {
                    FailedMessageIds       = failedIds,
                    NumberOfFailedMessages = failedIds.Length,
                    Context = stagingBatch.Context
                }).ConfigureAwait(false);
            }

            var msgLookup = messages.ToLookup(x => x.Id);

            stagingBatch.Status         = RetryBatchStatus.Forwarding;
            stagingBatch.StagingId      = stagingId;
            stagingBatch.FailureRetries = failedMessageRetriesById.Values.Where(x => msgLookup[x.FailedMessageId].Any()).Select(x => x.Id).ToArray();
            Log.Info($"Retry batch {stagingBatch.Id} staged with Staging Id {stagingBatch.StagingId} and {stagingBatch.FailureRetries.Count} matching failure retries");
            return(messages.Length);
        }
コード例 #45
0
 public StoredMessage(string messageId, TransportOperation[] transportOperations)
 {
     TransportOperations = transportOperations;
     Id = messageId;
     StoredAt = DateTime.UtcNow;
 }
コード例 #46
0
        internal async Task SpinOnce(CancellationToken cancellationToken)
        {
            if (NextRetrieval > currentTimeProvider() || cancellationToken.IsCancellationRequested)
            {
                return;
            }

            Logger.DebugFormat("Polling for timeouts at {0}.", currentTimeProvider());
            var timeoutChunk = await timeoutsFetcher.GetNextChunk(startSlice).ConfigureAwait(false);

            foreach (var timeoutData in timeoutChunk.DueTimeouts)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                if (startSlice < timeoutData.DueTime)
                {
                    startSlice = timeoutData.DueTime;
                }

                var dispatchRequest = ControlMessageFactory.Create(MessageIntentEnum.Send);

                dispatchRequest.Headers["Timeout.Id"] = timeoutData.Id;

                var transportOperation = new TransportOperation(dispatchRequest, new UnicastAddressTag(dispatcherAddress));
                await dispatcher.Dispatch(new TransportOperations(transportOperation), new TransportTransaction(), new ContextBag()).ConfigureAwait(false);
            }

            lock (lockObject)
            {
                var nextTimeToQuery = timeoutChunk.NextTimeToQuery;

                // we cap the next retrieval to max 1 minute this will make sure that we trip the circuit breaker if we
                // loose connectivity to our storage. This will also make sure that timeouts added (during migration) direct to storage
                // will be picked up after at most 1 minute
                var maxNextRetrieval = currentTimeProvider() + MaxNextRetrievalDelay;

                NextRetrieval = nextTimeToQuery > maxNextRetrieval ? maxNextRetrieval : nextTimeToQuery;

                Logger.DebugFormat("Polling next retrieval is at {0}.", NextRetrieval.ToLocalTime());
            }

            circuitBreaker.Success();
        }