I am attempting to perform request / reply with Rebus but also using the Windsor container NuGet package: https://github.com/rebus-org/Rebus.CastleWindsor
After looking at the following samples:
https://github.com/rebus-org/RebusSamples/tree/master/RequestReply
https://github.com/rebus-org/RebusSamples/tree/master/Integration
I have cobbled this example below together:
public class ContactModule : NancyModule
{
public ContactModule(IBus bus)
{
Get["/v1/contact"] = parameters =>
{
var contacts = new List<Contact>();
using (var activator = new BuiltinHandlerActivator())
{
var settings = new Settings();
activator.Handle<GetContactsResponse>(response =>
{
contacts = response.Contacts;
return Task.FromResult(0);
});
Configure.With(activator)
.Logging(l => l.ColoredConsole(LogLevel.Warn))
.Transport(t => t.UseRabbitMq(
settings.RabbitMQConnectionString,
settings.OutputQueueName)) // we listen for messages in the output queue
.Routing(r => r.TypeBased().MapAssemblyOf<GetContactsRequest>(settings.InputQueueName)) // but we publish to the input queue
.Options(o =>
{
o.EnableCompression();
o.EnableEncryption(settings.MessageEncryptionKey);
})
.Start();
activator.Bus.Publish(new GetContactsRequest``()).Wait();
}
return Response.AsJson(contacts);
};
}
}
I know it should probably look more like the below when using the Windsor container approach, but I do not know how to listen for the reply:
public class ContactModule : NancyModule
{
public ContactModule(IBus bus)
{
Get["/v1/contact"] = parameters =>
{
var contacts = new List<Contact>();
bus.Publish(new GetContactsRequest()).Wait();
// How do I listen for the reply?
return Response.AsJson(contacts);
};
}
}
My message handler:
public class GetContactsHandler : IHandleMessages<GetContactsRequest>
{
private readonly IBus _bus;
private readonly Settings _settings;
public GetContactsHandler(IBus bus, Settings settings)
{
_bus = bus;
_settings = settings;
}
public async Task Handle(GetContactsRequest request)
{
// Fetch contacts from db...
var contacts = new List<Contact>();
await _bus.Reply(new GetContactsResponse {Contacts = contacts});
}
}
My Rebus Windsor installer:
public class RebusInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
var settings = new Settings();
Configure.With(new CastleWindsorContainerAdapter(container))
.Logging(l => l.ColoredConsole(LogLevel.Warn))
.Transport(t => t.UseRabbitMqAsOneWayClient(
settings.RabbitMQConnectionString))
.Routing(r => r.TypeBased().MapAssemblyOf<GetContactsRequest>(settings.InputQueueName))
.Options(o =>
{
o.EnableCompression();
o.EnableEncryption(settings.MessageEncryptionKey);
})
.Start();
}
}
The problem I am facing is that I want to use the request / reply pattern in my web api to request a list of contacts, wait for the reply containing the retrieved contacts and return them to the api caller.
But If I want to use the Windsor container adapter for Rebus the IHandlerActivator interface does not expose the .Handle method which allows for registering inline message handlers, in which I am grabbing the contacts from the reply and then sending them back to the api caller.
Is there a way to do this, or am I approaching the problem incorrectly?
Edit: As you can see in the first example I am injecting in the IBus interface from the Windsor container. But if I use the injected bus how do I tell it to listen for the reply comming back from the message handler?
Update: Rebus.Async was exactly what I was looking for: https://github.com/rebus-org/Rebus.Async