# 7.1.8
# Resolved Issues
- Responding from a state machine through the InMemoryOutbox wasn't working as expected (opens new window)
- Kafka producer options can now be configured
IsResponseAccepted
will now return false if a ResponseAddress is not present- Azure Service Bus receive endpoints should now allow
PrefetchCount = 0
- RabbitMQ Quorum queues can now be configured using
.SetQuorumQueue()
, which sets the appropriate queue attributes - RabbitMQ queue attributes are now copied to the
_error
and_skipped
queues
# MassTransit Templates, Getting Started
A set of dotnet new
templates were released, which can be installed using dotnet new -i MassTransit.Templates
. The Getting Started documentation was updated to use the new templates and a new sample was added (opens new window) based on the documentation. Most of the new documentation will be written from a container-first perspective, starting with AddMassTransit and subsequently documenting the container-free versions where available.
# Delayed Message Delivery / Redelivery
It is now possible to configure delayed redelivery using the message transport. This approach works directly with the message transport, and does not use any configured message scheduler. A message scheduler can still be configured and used for regular message scheduling, but the transport message delay feature will be used for redelivery. This can significantly reduce the load on Quartz/Hangfire scheduling and separates the concerns of message redelivery and message scheduling.
The configuration syntax is the same as scheduled redelivery, but with a new transport-independent extension method:
cfg.ReceiveEndpoint("submit-order", e =>
{
e.UseDelayedRedelivery(r => r.Intervals(TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(30)));
e.UseMessageRetry(r => r.Immediate(5));
e.UseInMemoryOutbox();
e.ConfigureConsumer<SubmitOrder>();
});
The in-memory transport was updated to support delayed message delivery, making it easier to test delayed message scenarios.
The new delayed support can also be used a message scheduler, regardless of transport. To configure the delayed exchange scheduler, see the example below.
namespace SchedulingDelayed
{
using System;
using MassTransit;
using Microsoft.Extensions.DependencyInjection;
public class Program
{
public static void Main()
{
var services = new ServiceCollection();
services.AddMassTransit(x =>
{
x.AddDelayedMessageScheduler();
x.UsingInMemory((context, cfg) =>
{
cfg.UseDelayedMessageScheduler();
cfg.ConfigureEndpoints(context);
});
});
}
}
}
# ExceptionInfo Data
The ExceptionInfo
type has a new property, Data
, which is a IDictionary<string, object>
. This extra property supports the inclusion of application/exception specific data with the exception details. Since MassTransit does not support the directly serialization of Exception
types (nor should it), this makes it possible to include additional values when an exception is thrown.
This is an opt-in approach, and by default no exception data will be added. This was decided to avoid accidental leakage of sensitive data.
A new exception type, MassTransitApplicationException
, can be used to opt-in to the automatic propagation of Data properties into ExceptionInfo.Data
. For example, data values can be explicitly added when the exception is caught and thrown.
class SubmitOrderConsumer :
IConsumer<SubmitOrder>
{
public Task Consume(ConsumeContext<SubmitOrder> context)
{
try
{
throw new IntentionalTestException("This was intentional");
}
catch (Exception exception)
{
throw new MassTransitApplicationException(exception, new
{
context.Message.OrderNumber,
context.Message.CustomerNumber,
});
}
}
}
The built-in Data
property of Exception
will also be used as a source when using MassTransitApplicationException
. In the example below, the Data
properties are added to the exception (framework and other libraries use this to store information, this example just does it to show the usage).
class SubmitOrderConsumer :
IConsumer<SubmitOrder>
{
public Task Consume(ConsumeContext<SubmitOrder> context)
{
try
{
var exception = new IntentionalTestException("This was intentional");
exception.Data.Add("Username", "Frank");
exception.Data.Add("CustomerId", 27);
throw exception;
}
catch (Exception exception)
{
throw new MassTransitApplicationException(exception);
}
}
}
# Raw JSON Message Headers
The Raw JSON message serializer/deserializer was updated to support transport message headers, offering better support for messages without a regular MassTransit message envelope. The supported message headers include:
Name | Type | Property | Notes |
---|---|---|---|
MessageId | Guid | MessageId | |
CorrelationId | Guid | CorrelationId | |
ConverationId | Guid | ConversationId | |
RequestId | Guid | RequestId | |
MT-InitiatorId | Guid | InitiatorId | |
MT-Source-Address | Uri | SourceAddress | |
MT-Response-Address | Uri | ResponseAddress | |
MT-Fault-Address | Uri | FaultAddress | |
MT-MessageType | string | SupportedMessageTypes | ; delimited |
MT-Host-Info | JSON | Host | serialized Host |
The default configuration doesn't change the existing behavior. When configuring the use of the Raw JSON serializer, new options are available:
Option | Description |
---|---|
AnyMessageType | Default behavior, any T is allowed. Do not specify to check the transport message type header |
AddTransportHeaders | Default behavior, headers are written to the transport and used |
CopyHeaders | Optional, will copy non-MassTransit headers to outbound messages |
These options are specified as a parameter to cfg.UseRawJsonSerializer(options)
.
# State Machine Delay Provider
When configuring a message schedule in an Automatonymous state machine, instead of specifying a fixed delay, a DelayProvider
can be configured. This enables dynamic delay periods based upon the contents of the state machine instance. The delay can still be dynamically specified when using .Schedule()
based upon the instance and/or message contents.
# Azure Blob Storage Package Change
The Azure Blob Storage Message Data repository was changed to use the new standard Azure packages. This may require slight reconfiguration, but should work as it did previously.