public async Task Should_update_retry_headers_when_present() { var delayedRetryExecutor = CreateExecutor(); var originalHeadersTimestamp = DateTimeOffsetHelper.ToWireFormattedString(new DateTime(2012, 12, 12, 0, 0, 0, DateTimeKind.Utc)); var incomingMessage = CreateMessage(new Dictionary <string, string> { { Headers.DelayedRetries, "2" }, { Headers.DelayedRetriesTimestamp, originalHeadersTimestamp } }); var now = DateTime.UtcNow; await delayedRetryExecutor.Retry(incomingMessage, TimeSpan.Zero, new TransportTransaction(), default); var outgoingMessageHeaders = dispatcher.UnicastTransportOperations.Single().Message.Headers; Assert.AreEqual("3", outgoingMessageHeaders[Headers.DelayedRetries]); Assert.AreEqual("2", incomingMessage.Headers[Headers.DelayedRetries]); var utcDateTime = DateTimeOffsetHelper.ToDateTimeOffset(outgoingMessageHeaders[Headers.DelayedRetriesTimestamp]); // the serialization removes precision which may lead to now being greater than the deserialized header value var adjustedNow = DateTimeOffsetHelper.ToDateTimeOffset(DateTimeOffsetHelper.ToWireFormattedString(now)); Assert.That(utcDateTime, Is.GreaterThanOrEqualTo(adjustedNow)); Assert.AreEqual(originalHeadersTimestamp, incomingMessage.Headers[Headers.DelayedRetriesTimestamp]); }
public async Task Message_should_be_processed_when_ignoringTTBRHeaders() { var context = await Scenario.Define <Context>() .WithEndpoint <SomeEndpoint>(endpoint => endpoint .CustomConfig(e => { var transportConfig = (MsmqTransport)e.ConfigureTransport(); transportConfig.IgnoreIncomingTimeToBeReceivedHeaders = true; }) .When(async(session, ctx) => { var sendOptions = new SendOptions(); sendOptions.RouteToThisEndpoint(); sendOptions.SetHeader(Headers.TimeSent, DateTimeOffsetHelper.ToWireFormattedString(DateTime.UtcNow.AddSeconds(-10))); sendOptions.SetHeader(Headers.TimeToBeReceived, TimeSpan.FromSeconds(5).ToString()); await session.Send(new SomeMessage(), sendOptions); ctx.WasSent = true; }) ) .Run(TimeSpan.FromSeconds(5)); Assert.IsTrue(context.WasSent, "Message was sent"); Assert.IsTrue(context.WasReceived, "Message was not processed"); }
public async Task Message_should_not_be_processed() { var tcs = new Lazy <CancellationTokenSource>(() => new CancellationTokenSource(TimeSpan.FromSeconds(5))); var context = await Scenario.Define <Context>() .WithEndpoint <SomeEndpoint>(endpoint => endpoint .CustomConfig(e => { var transportConfig = (MsmqTransport)e.ConfigureTransport(); transportConfig.IgnoreIncomingTimeToBeReceivedHeaders = false; }) .When(async(session, ctx) => { var sendOptions = new SendOptions(); sendOptions.RouteToThisEndpoint(); sendOptions.SetHeader(Headers.TimeSent, DateTimeOffsetHelper.ToWireFormattedString(DateTime.UtcNow.AddSeconds(-10))); sendOptions.SetHeader(Headers.TimeToBeReceived, TimeSpan.FromSeconds(5).ToString()); await session.Send(new SomeMessage(), sendOptions); ctx.WasSent = true; }) ) .Done(c => tcs.Value.IsCancellationRequested) // wait at least 5 seconds to give the endpoint time to process any message .Run(); Assert.IsTrue(context.WasSent, "Message was sent"); Assert.IsFalse(context.WasReceived, "Message was processed"); }
public static void SetExceptionHeaders(Dictionary <string, string> headers, Exception e) { headers["NServiceBus.ExceptionInfo.ExceptionType"] = e.GetType().FullName; if (e.InnerException != null) { headers["NServiceBus.ExceptionInfo.InnerExceptionType"] = e.InnerException.GetType().FullName; } headers["NServiceBus.ExceptionInfo.HelpLink"] = e.HelpLink; headers["NServiceBus.ExceptionInfo.Message"] = e.GetMessage().Truncate(16384); headers["NServiceBus.ExceptionInfo.Source"] = e.Source; headers["NServiceBus.ExceptionInfo.StackTrace"] = e.ToString(); headers["NServiceBus.TimeOfFailure"] = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow); // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (e.Data == null) // ReSharper disable HeuristicUnreachableCode { return; } // ReSharper restore HeuristicUnreachableCode foreach (DictionaryEntry entry in e.Data) { if (entry.Value == null) { continue; } headers["NServiceBus.ExceptionInfo.Data." + entry.Key] = entry.Value.ToString(); } }
public async Task Should_honor_stored_delivery_constraints() { var messageId = "id"; var options = new Dictionary <string, string>(); var deliverTime = DateTimeOffset.UtcNow.AddDays(1); var maxTime = TimeSpan.FromDays(1); options["Destination"] = "test"; options["DeliverAt"] = DateTimeOffsetHelper.ToWireFormattedString(deliverTime); options["DelayDeliveryFor"] = TimeSpan.FromSeconds(10).ToString(); options["TimeToBeReceived"] = maxTime.ToString(); fakeOutbox.ExistingMessage = new OutboxMessage(messageId, new[] { new NServiceBus.Outbox.TransportOperation("x", options, new byte[0], new Dictionary <string, string>()) }); var context = CreateContext(fakeBatchPipeline, messageId); await Invoke(context); Assert.True(fakeBatchPipeline.TransportOperations.First().DeliveryConstraints.TryGet(out DelayDeliveryWith delayDeliveryWith)); Assert.AreEqual(TimeSpan.FromSeconds(10), delayDeliveryWith.Delay); Assert.True(fakeBatchPipeline.TransportOperations.First().DeliveryConstraints.TryGet(out DoNotDeliverBefore doNotDeliverBefore)); Assert.AreEqual(deliverTime.ToString(), doNotDeliverBefore.At.ToString()); Assert.True(fakeBatchPipeline.TransportOperations.First().DeliveryConstraints.TryGet(out DiscardIfNotReceivedBefore discard)); Assert.AreEqual(maxTime, discard.MaxTime); Assert.Null(fakeOutbox.StoredMessage); }
public void When_roundtripping_constructed_date_should_be_equal() { var date = new DateTimeOffset(2016, 8, 29, 16, 37, 25, 75, TimeSpan.Zero); var dateString = DateTimeOffsetHelper.ToWireFormattedString(date); var result = DateTimeOffsetHelper.ToDateTimeOffset(dateString); Assert.AreEqual(date, result); }
static string ValueToString(object value) { if (value is byte[] bytes) { return(Encoding.UTF8.GetString(bytes)); } if (value is Dictionary <string, object> dictionary) { var sb = new StringBuilder(); foreach (var kvp in dictionary) { sb.Append(kvp.Key); sb.Append("="); sb.Append(ValueToString(kvp.Value)); sb.Append(","); } if (sb.Length > 0) { sb.Remove(sb.Length - 1, 1); } return(sb.ToString()); } if (value is List <object> list) { var sb = new StringBuilder(); foreach (var entry in list) { sb.Append(ValueToString(entry)); sb.Append(";"); } if (sb.Length > 0) { sb.Remove(sb.Length - 1, 1); } return(sb.ToString()); } if (value is global::RabbitMQ.Client.AmqpTimestamp timestamp) { return(DateTimeOffsetHelper.ToWireFormattedString(UnixEpoch.AddSeconds(timestamp.UnixTime))); } return(value?.ToString()); }
public void When_roundtripping_UtcNow_should_be_accurate_to_microseconds() { var date = DateTimeOffset.UtcNow; var dateString = DateTimeOffsetHelper.ToWireFormattedString(date); var result = DateTimeOffsetHelper.ToDateTimeOffset(dateString); Assert.AreEqual(date.Year, result.Year); Assert.AreEqual(date.Month, result.Month); Assert.AreEqual(date.Day, result.Day); Assert.AreEqual(date.Hour, result.Hour); Assert.AreEqual(date.Minute, result.Minute); Assert.AreEqual(date.Second, result.Second); Assert.AreEqual(date.Millisecond, result.Millisecond); Assert.AreEqual(date.Microseconds(), result.Microseconds()); Assert.AreEqual(date.Offset, result.Offset); }
public void ShouldCapTheRetryMaxTimeTo24Hours() { var now = DateTime.UtcNow; var baseDelay = TimeSpan.FromSeconds(10); var policy = CreatePolicy(maxImmediateRetries: 0, maxDelayedRetries: 2, delayedRetryDelay: baseDelay); var moreThanADayAgo = now.AddHours(-24).AddTicks(-1); var headers = new Dictionary <string, string> { { Headers.DelayedRetriesTimestamp, DateTimeOffsetHelper.ToWireFormattedString(moreThanADayAgo) } }; var errorContext = CreateErrorContext(headers: headers); var result = policy(errorContext); Assert.IsInstanceOf <MoveToError>(result); }
public static void SetExceptionHeaders(Dictionary <string, string> headers, Exception e) { headers["NServiceBus.ExceptionInfo.ExceptionType"] = e.GetType().FullName; if (e.InnerException != null) { headers["NServiceBus.ExceptionInfo.InnerExceptionType"] = e.InnerException.GetType().FullName; } headers["NServiceBus.ExceptionInfo.HelpLink"] = e.HelpLink; headers["NServiceBus.ExceptionInfo.Message"] = e.GetMessage().Truncate(16384); headers["NServiceBus.ExceptionInfo.Source"] = e.Source; headers["NServiceBus.ExceptionInfo.StackTrace"] = e.ToString(); headers["NServiceBus.TimeOfFailure"] = DateTimeOffsetHelper.ToWireFormattedString(DateTimeOffset.UtcNow); foreach (DictionaryEntry entry in e.Data) { if (entry.Value == null) { continue; } headers["NServiceBus.ExceptionInfo.Data." + entry.Key] = entry.Value.ToString(); } }
void SendToDelayedDeliveryQueue(TransportTransaction transaction, UnicastTransportOperation transportOperation) { onSendCallback?.Invoke(transaction, transportOperation); var message = transportOperation.Message; transportOperation.Properties[TimeoutDestination] = transportOperation.Destination; DateTimeOffset deliverAt; if (transportOperation.Properties.DelayDeliveryWith != null) { deliverAt = DateTimeOffset.UtcNow + transportOperation.Properties.DelayDeliveryWith.Delay; } else // transportOperation.Properties.DoNotDeliverBefore != null { deliverAt = transportOperation.Properties.DoNotDeliverBefore.At; } transportOperation.Properties[TimeoutDestination] = transportOperation.Destination; transportOperation.Properties[TimeoutAt] = DateTimeOffsetHelper.ToWireFormattedString(deliverAt); var destinationAddress = MsmqAddress.Parse(timeoutsQueue); foreach (var kvp in transportOperation.Properties) { //Use add to force exception if user adds a custom header that has the same name as the prefix + property name transportOperation.Message.Headers.Add($"{MsmqUtilities.PropertyHeaderPrefix}{kvp.Key}", kvp.Value); } try { using (var q = new MessageQueue(destinationAddress.FullPath, false, transportSettings.UseConnectionCache, QueueAccessMode.Send)) { using (var toSend = MsmqUtilities.Convert(message)) { toSend.UseDeadLetterQueue = true; //Always used DLQ for delayed messages toSend.UseJournalQueue = transportSettings.UseJournalQueue; if (transportOperation.RequiredDispatchConsistency == DispatchConsistency.Isolated) { q.Send(toSend, string.Empty, GetIsolatedTransactionType()); return; } if (TryGetNativeTransaction(transaction, out var activeTransaction)) { q.Send(toSend, string.Empty, activeTransaction); return; } q.Send(toSend, string.Empty, GetTransactionTypeForSend()); } } } catch (MessageQueueException ex) { if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound) { throw new QueueNotFoundException(timeoutsQueue, $"Failed to send the message to the local delayed delivery queue [{timeoutsQueue}]: queue does not exist.", ex); } ThrowFailedToSendException(timeoutsQueue, ex); } catch (Exception ex) { ThrowFailedToSendException(timeoutsQueue, ex); } }