-
Notifications
You must be signed in to change notification settings - Fork 0
Learn MassTransit
In this example:
-
the
Consumer2
sends the Input1 request, both theConsumer12
andConsumer13
will be triggered, the first response comming out will be returned to theConsumer2
-
The
Consumer2
can depend on theIMediator
interface to make the request => but it is better to makeConsumer2
depend on the more specificIRequestClient<Input1>
instead, so that it won't be able to use theIMediator
to triggered itself (recursively). In order to make the typeIRequestClient<Input1>
available to the DI Container, then you will have to register it withcfg.AddRequestClient<Input1>()
//we want to validate the DI graph on startup
builder.Host.UseDefaultServiceProvider(o =>
{
o.ValidateOnBuild = true;
o.ValidateScopes = true;
});
builder.Services.AddMediator(cfg =>
{
cfg.AddConsumers(typeof(Consumer12).Assembly); //add all the consumers in the assembly to the DI graph
cfg.AddRequestClient<Input1>(); //add `IRequestClient<Input1>` to the DI graph
cfg.AddRequestClient<Input2>(); //add `IRequestClient<Input2>` to the DI graph
});
public class Consumer13 : IConsumer<Input1>
{
public async Task Consume(ConsumeContext<Input1> context){...}
}
public class Consumer12 : IConsumer<Input1>
{
public async Task Consume(ConsumeContext<Input1> context){...}
}
public class Consumer2 : IConsumer<Input2>
{
public Consumer2(IRequestClient<Input1> requestClient1){...}
public async Task Consume(ConsumeContext<Input2> context)
{
requestClient1.GetResponse(new Input1) // it will trigger both the Consumer12 and the Consumer13, and take the first response
}
}
In this example:
- The Http request arrives to the
FooController
-
FooController
requests theConsumer2
(by sending theInput2
) -
Consumer2
will requests theConsumer1
(by sending theInput1
) - Both
FooController
,Consumer1
andConsumer2
depends onFoo
-
Foo
is registered as scoped in the DI container.
Program.cs
builder.Services.AddMediator(cfg =>
{
cfg.AddConsumers<Consumer1>();
cfg.AddConsumers<Consumer2>();
})
builder.Services.AddScoped<IFoo, Foo>();
..
app.MapControllers();
----
public class FooController : ControllerBase {
public FooController(IFoo foo) {...}
requestClient.GetResponse(new Input2); //call the consumer2
}
public class Consumer1 : IConsumer<Input1> {
public Consumer1(IFoo foo) {...}
}
public class Consumer2 : IConsumer<Input2> {
public Consumer2(IFoo foo) {...}
requestClient.GetReponse(new Input1) //call the consumer 1
}
If you think that in the same HttpRequest you got the same instance of Foo
then it is WRONG
- When the HTTP request arrives to the
FooController
then theFooController
got a new instance ofFoo
scoped to the HTTP request. - When the
FooController
requestsConsumer2
then theConsumer2
got other instance ofFoo
scoped to this MassTransit request (request withInput2
as payload) - When the
Consumer2
requestsConsumer1
then theConsumer1
got other instance ofFoo
scoped to this MassTransit request (request withInput1
as payload)
In this example, for each Http request, you will got 3 differents instances of Foo
. Each instance have a different scope
Now, what if you want to share a common Foo
instance between FooController
, Consumer1
and Consumer2
?
=> You can register the Foo instance to the HttpContext
Program.cs
builder.Services.AddHttpContextAccessor();
----
public class FooController : ControllerBase
{
public FooController(IFoo foo) {...}
[HttpGet]
public void Get()
{
HttpContext.Items["Foo"] = _foo; //register the instance of Foo which is scoped to the Http request to the HttpContext
}
}
public class Consumer1 : IConsumer<Input1> {
public Consumer1(IHttpContextAccessor httpContextAccessor) {...}
...
IFoo? foo = _httpContextAccessor.HttpContext?.Items["Foo"] as IFoo; //get the foo instance from the HttpContext
}
public class Consumer2 : IConsumer<Input2> {
public Consumer2(IHttpContextAccessor httpContextAccessor) {...}
...
IFoo? foo = _httpContextAccessor.HttpContext?.Items["Foo"] as IFoo; //get the foo instance from the HttpContext
}
https://docs.particular.net/nservicebus/outbox/
Sample MassTransit outbox