# 7.0.7
# Message Scope for Scoped Filters
Scoped Filters are resolved from the container for each message. When used with the InMemoryOutbox, which publishes/sends messages after the consumer has completed, errors may occur or the scope may not be the same as the scope used by the consumer. To deal with this issue, new configuration methods have been added to create a message scope.
# Microsoft Dependency Injection
Bus.Factory.CreateUsingInMemory(cfg =>
{
cfg.ReceiveEndpoint("input-queue", endpoint =>
{
endpoint.UseMessageRetry(r => r.Intervals(1000, 2000));
endpoint.UseMessageScope(serviceProvider);
endpoint.UseInMemoryOutbox();
endpoint.ConfigureConsumer<ProducingConsumer>(Registration);
});
});
# Autofac
Bus.Factory.CreateUsingInMemory(cfg =>
{
cfg.ReceiveEndpoint("input-queue", endpoint =>
{
endpoint.UseMessageRetry(r => r.Intervals(1000, 2000));
endpoint.UseMessageLifetimeScope(container);
endpoint.UseInMemoryOutbox();
endpoint.ConfigureConsumer<ProducingConsumer>(Registration);
});
});
# New Consumer Saga Interface Type
Consumer Sagas can now be correlated using the new or existing policy, allowing a single message type to either create a new or use an existing saga instance. By adding the InitiatedByOrOrchestrates<T>
interface to the saga, the appropriate policy will be configured.
public class ConsumerSaga :
InitiatedByOrOrchestrates<EventMessage>
{
public async Task Consume(ConsumeContext<EventMessage> context)
{
}
}
# ReadOnly State Machine Events
Automatonymous state machine sagas can now specify an Event as read-only. When an event is read-only, any changes to the saga instance are NOT saved to the saga repository.
class ReadOnlyStateMachine :
MassTransitStateMachine<ReadOnlyInstance>
{
public ReadOnlyStateMachine()
{
InstanceState(x => x.CurrentState);
Event(() => StatusCheckRequested, x =>
{
x.ReadOnly = true;
});
Initially(
When(Started)
.Then(context => context.Instance.StatusText = "Started")
.Respond(context => new StartupComplete {CorrelationId = context.Instance.CorrelationId})
.TransitionTo(Running)
);
During(Running,
When(StatusCheckRequested)
.Respond(context => new Status
{
CorrelationId = context.Instance.CorrelationId,
StatusText = context.Instance.StatusText
})
.Then(context => context.Instance.StatusText = "Running") // this change won't be saved
);
}
public State Running { get; private set; }
public Event<Start> Started { get; private set; }
public Event<CheckStatus> StatusCheckRequested { get; private set; }
}
The in-memory saga repository isn't able to undo changes, since they are applied to the saga instance in memory, just FYI.
# Transport Headers
When using the RawJsonMessageDeserializer
, the ConsumeContext.Headers
collection now includes the transport headers.
# MongoDB Audit Store
MongoDB can now be configured as an audit store.
Bus.Factory.CreateUsingInMemory(cfg =>
{
cfg.UseMongoDbAuditStore(database, auditCollectionName);
});
# C# 9 Record Support
The Rosyln analyzer has been updated to work with C# 9 records, and should no longer report invalid contract types for records.
# Job Consumers
Suspect jobs (jobs that disappear, either due to a service failure/shutdown or whatever) are now faulted properly. Suspect jobs can also be retried by specifying a SuspectJobRetryCount
and SuspectJobRetryDelay
during the job service configuration.