EasyNetQ - receiving from existing queue - c#

I am looking at using EasyNetQ for interacting with RabbitMQ and wondering if it can support following case:
Queue is declared externally with some arbitrary arguments (e.g. x-message-ttl)
Client code using EasyNetQ sends and receives messages from that queue.
Possibilities I have found are:
Simple IBus API requires that queue has default parameters
Advanced IAdvancedBus API allows to specify arguments of the declared-queue but not all (e.g. x-max-length can't be set)
The question is can I just use existing queue with custom parameters and without need to specify them?

If the queue already exists and you know its name, couldn't you use the IAdvancedBus.Consume<T> method (and not worry about IAdvancedBus.QueueDeclare)?
For example:
var queueName = "TheNameOfYourExistingQueue";
var existingQueue = new EasyNetQ.Topology.Queue(queueName, false);
// bus should be an instance of IAdvancedBus
bus.Consume<TypeOfYourMessage>(existingQueue,
(msg, info) =>
{
// Implement your handling logic here
});
Note that EasyNetQ might have trouble automatically deserializing messages into instances of TypeOfYourMessage. If that is the case, one way to solve it would be to bypass EasyNetQ's message serializer so that you can access the byte array of the message directly. Use the following overload to Consume if you wish to go that route:
void Consume(IQueue queue, Func<Byte[], MessageProperties, MessageReceivedInfo, Task> onMessage);

Even with solution 10477404, parameters like isDurable, isExclusive, isAutoDelete, and arguments must match the original Queue declaration to avoid creating a new one.
For safety, and if you have a way to know the original queue declaration parameters, use them to create the queue with IAdvancedBus.QueueDeclare() or IAdvancedBus.QueueDeclareAsync()

Related

Catch-all to match all message types in SignalR server

We use SignalR in several applications – it’s very handy and works well! :-) We usually have a C# server side and a JavaScript client.
But now we have a “special need”: On the server side, we would like to have one and the same method executed regardless of what message type the client sends. A kind of “catch-all method” in the SignalR server. (It’s for a special testing purpose – there will be added new message types all the time. The message parameter is always an object.)
Is this possible? I know about the HubMethodNameAttribute, and I basically would like to be able to use some sort of wildcard there. Something equal to this in the hub class:
[HubMethodName("*")]
public Task MyCatchAll(object par)
{
// handle the message
}
Or some other way to always get the same method called, regardless of message type.
We don’t want to have to maintain a list of all possible messages, like this:
public Task OneOfTheMessageTypes(object par) => MyCatchAll(par);
public Task AnotherMessageType(object par) => MyCatchAll(par);
public Task AndYetAnotherOne(object par) => MyCatchAll(par);
public Task AndSoOn(object par) => MyCatchAll(par);
...
(I’ve tried using an IHubFilter, but that isn’t called until SignalR has identified the method to call; can’t be used for message types not defined.)
I’d be most grateful for some help from a SignalR expert! :-)
/Anders from Sweden

Generating message handlers for Rebus in runtime

I'm facing a problem where I want to use Rebus to subscribe to and handle messages in rabbitmq. There are multiple message types defined in a third party assembly and new message types will be added to that assembly on a regular basis.
I need to somehow make Rebus subscribe and handle all those message types and forward them (Publish) to another rabbitmq instance. My service is essentially forwarding messages and also adding a custom rebus header when doing so.
The issue is that I do not want to generate handler classes for each and every message type (since the functionality is the same irrespective of the message type). I also dont want to update my code (writing new handler classes) every time a new message type is added in the third party assembly.
I tried using TypeBuilder to dynamically creating message handler classes for every type found by reflection but it feels kind of messy so I hope there is another way?
Code below outlines what I was kind of hoping to achieve even though the code doesn´t compile.
public void SubscribeAndHandleMessages()
{
// These types will be determined runtime by using reflection but thats omitted for clarity
var messageTypes = new List<Type>(){typeof(MessageA), typeof(MessageB)};
var activator = new BuiltinHandlerActivator();
Configure.With(activator)
.Transport(t => t.UseRabbitMq(_rabbitConnectionString, "MyQueue"))
.Start();
//Subscribe and register handlers
foreach (var type in messageTypes)
{
activator.Bus.Subscribe(type); //This works, I can see the queue subscribing to the correct topics
activator.Handle<type>(async (bus, context, message) => //This doesnt work since type is not known at compile time
{
//Forwarding to another rabbit instance, same handling for all types of messages
});
}
}
Once you've established the necessary subscriptions, you only need to be able to handle all kinds of messages that you receive.
The best way to do that with Rebus, is to avoid the ordinary message processing pipeline (deserialize => look up handlers => dispatch) and instead handle the message in its raw form (i.e. in its "transport message" form).
You can do that with Rebus' transport message forwarding capability. With it, a 100% generic message handler could look like this:
Configure.With(activator)
.Transport(t => t.UseInMemoryTransport(new InMemNetwork(), "router-tjek"))
.Routing(r => r.AddTransportMessageForwarder(async transportMessage =>
{
var headers = transportMessage.Headers; //< Dictionary<string, string>
var body = transportMessage.Body; //< byte[]
// handle the message here, e.g.
// by deserializing the body into a JObject,
// storing the bytes in a database, or by
// forwarding the message to another queue
return // appropriate forward action here
}))
.Start();
You can read more about it here: Transport message forwarding

How to structure communication between TcpListener and TcpClient after initial socket connection is made

So this is maybe pretty simple for network programming dudes but I'm a little confused about this. Let me try to ask given an example of usage.
Say I were to create a chat server with clients being able to join with a username. No accounts or passwords. Just username.
I have a working Echo Server example running that uses async calls so all that is good. Now I need to define some message handling between the client and the server.
Lets say the client now connects and it wants to get the list of connected users. How would I go about doing that?
My thought is that I create a function called BeginGetConnectedUsers and that will send message to the server. The server will then reply with a list of users but because I'm using async calls I'll now have my accept code look at the message and figure out that it is a reply from a BeginGetConnectedUsers so it will send the data to a EndGetConnectedUsers.
But I have no idea if this is a good way to do something like this?
But also with this design I'll have to pair every BeginGet function with an EndGet function. This could be made more readable with the async await style but though but that may not be preferable either.
I have no experience with how to structure the following communication between client and server when they have to start exchanging all the interesting data stuff...
And advice? Places to look? All my google searches that include the work TCPLISTENER will all show me examples of Echo Servers and I already know how to do that.
There are many posible implementations here.
I woudl implement an strategy pattern or a controller pattern. Other options are state machines (deterministic automatas) or even a simple and big switch case.
So basically you have only one function to receive the messages from the wire.
All the messages implements the same interface may be
IMessage<T>
{
string Type {get;set;}
T Data {get;set;}
}
So when you get the message you use the Type property to route the T Data to the actual method you want.
In a simple implementation using a controller, you anotate the controller methods with an attribute indicating the message type you want to manage:
class Controller
{
[Messagetype("GetConnectedUsersResponse")]
Response GetConnectedUsers(IEnumerable<User> users)
{
//...
}
[Messagetype("AnothermessageType")]
Response OtherStuffToDo(....)
{
//...
}
}
When you receives the message, by using some simple reflection you dynamically call to the method wich has the attibute with the matching message type attribute.
If you dont like reflection another option (among a lot of docens else) is to use an strategy patter
So you can register some message Handlers by key in your IoC container for example.
All hadlers implement a function lets say
interface MessageHandler<T>
{
Response Handle(T Data);
}
When you receive the message you just resolve the handler using your favourite IoC container (resolving by name is lately considered as an atipattern, so take it with a pinch of salt)
var handler = container.resolve(message.Type);
var response = handler.handle(message.Data);
In both implementations you should define how you respond (if you do) and adjust the "Response" return type (May be you just dont have response so it is void)

Publishing to multiple Rebus queues with different stores

We have one application that publishes messages - PublishApp.
The messages (MessageA and MessageB) are picked up by two different consumer apps (ConsumerA and ConsumerB).
All applications use SQL Server as a transport and Windsor configuration, but the two Consumers have different databases in SQL Server.
How can we configure PublishApp to publish MessageA for ConsumerA and MessageB for ConsumerB?
I have tried using DetermineMessageOwnership as described here, but that doesn't seem to actually be called (no breakpoints hit). I'm a little mystified as to what the string endpoints returned should be.
I was hoping that I could set up an IBus component in Windsor with a specific name, then reference that by name when setting up my MessageB-publishing class. However it's not clear how to set up an IBus in Windsor outside of the magic box that does it all for me.
Fiddling with Windsor configuration leads me to a Windsor error if I try to call Configure.With(new WindsorContainerAdapter(container)) twice, as it is interpreted as registering the IBus interface twice. I can't see an extension point here to give one of the IBus instances a name, and hence differentiate them in Windsor.
Alternatively, trying to reuse the Configure.With... call throws an error telling me I have called .Transport() on the configurer twice, which is also not allowed (but which would let me use a different connection string...)
Adding XML configuration will let me specify different endpoints for my different messages, but not different SQL connection strings.
What I would really like to end up with is something like:
// Set up Bus A
var busA = Configure.With(new WindsorContainerAdapter(container))
.Transport(tc => tc.UseSqlServerInOneWayClientMode("ConnectionStringA"))
.Subscriptions(sc => sc.StoreInSqlServer("ConnectionStringA", "RebusSubscriptions"))
.CreateBus()
.Start();
// Set up Bus B
var busB = Configure.With(new WindsorContainerAdapter(container))
.Transport(tc => tc.UseSqlServerInOneWayClientMode("ConnectionStringB"))
.Subscriptions(sc => sc.StoreInSqlServer("ConnectionStringB", "RebusSubscriptions"))
.CreateBus()
.Start();
// Register Bus A in Windsor
container.Register(Component.For<IBus>()
.Named("BusA")
.Instance(busA));
// Register a class that depends on IBus, and set it to use Bus A
container.Register(Component.For<IPublishA>()
.ImplementedBy<PublishA>()
.DependsOn(Dependency.OnComponent(typeof(IBus), "BusA"));
// And a registration also for IBus B, and for IPublishB to reference named "BusB"
Note: I do not want to listen to multiple buses, only publish events to them. Other applications are monitoring the queues, and each application only listens for one event on one queue.
We resolved this in the end by dropping the WindsorContainerAdaptor. Since we're not handling any messages, only publishing/sending, we don't need any of the 'handler' stuff in the container adaptor and we can switch the registration of the IBus component around to happen outside of the configuration/starting, rather than inside it. This gives us the control to name the IBus registration.
public static void ConfigureAndStartBus(IWindsorContainer container)
{
_RegisterBus(container, "ConnectionStringA" "BusA");
_RegisterBus(container, "ConnectionStringB" "BusB");
}
private static void _RegisterBus(IWindsorContainer container, string connectionString, string busName)
{
var bus = Configure.With(new BuiltinContainerAdapter())
.Transport(tc => tc.UseSqlServerInOneWayClientMode(connectionString))
.Subscriptions(sc => sc.StoreInSqlServer(connectionString, "RebusSubscriptions"))
.CreateBus()
.Start();
container.Register(
Component.For<IBus>()
.Named(busName)
.LifestyleSingleton()
.Instance(bus));
}
Then in class PublishA, we can register it with a dependency on BusA, and PublishB can be registered with a dependency on BusB. The messages go to separate databases, and are picked up by separate subscribers to do work in those different databases.
First off: There's no way (at least at the moment) to ship messages between two SQL Server databases. In order for messages to be sent/published between endpoints, you need to use one single table in one shared database.
Your setup hints at something being off there, since you're using "ConnectionStringA" and "ConnectionStringB" for the transports.
It's not clear to me whether you actually want/need to do pub/sub messaging - pub/sub is what you would usually use when you want multiple recipients of each message, which would usually be some kind of event (i.e. a message whose name is in the past tense, as in: "this and that happened").
If you want one specific recipient for a message, you want to bus.Send that message, and that is when your endpoint mappings will be hit in order to get a destination for the message.
If you tell me some more about exactly what you're trying to achieve, I am sure I can help you :)

Constructor not being called in type derieved from DuplexChannelFactory<T>

I have question about the article in here. The related code is as follow.
public CustomClientChannel(string configurationPath) : base(typeof(T))
{
this.configurationPath = configurationPath;
base.InitializeEndpoint((string)null, null);
}
protected override ServiceEndpoint CreateDescription()
{
ServiceEndpoint serviceEndpoint = base.CreateDescription();
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = this.configurationPath;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
ServiceModelSectionGroup group = ServiceModelSectionGroup.GetSectionGroup(config);
ChannelEndpointElement selectedEndpoint = null;
......
}
The first function is the constructor of the class and the second one overloads the CreateDescription function in DuplexChannelFactory since the class inherents from DuplexChannelFactory.
However, when I use this class to create an object, the code runs directly into CreateDescription().
Therefore, even though I pass a configurationPath to the constructor, the this.configurationPath is still null.
If I inherent CustomClientChannel class from ChannelFactory, then it works fine.
Please help to see what is wrong and what is the difference between ChannelFactory and DuplexChannelFactory? I am using netTcpBinding. Thank you.
Your constructor is calling into a base constructor that takes a single type.
: base(typeof(T))
Both ChannelFactory<T> and DuplexChannelFactory<T> implement a protected constructor that takes a single type, but they are different.
ChannelFactory<T> wants the channel type.
DuplexChannelFactory<T> want the callback instance type
In other words, they do completely different things and can have completely different code paths. Protected constructors are to be used by derived types only, and generally infer some level of knowledge of how the class hierarchy works.
You would be better picking the public constructor that you would normally use, and calling that instead. If that is not possible then you need to work out the appropriate DuplexChannelFactory constructor to call instead.
Let's start with
what is the difference between ChannelFactory and
DuplexChannelFactory?
First it is necessary to understand the difference between simplex and duplex communications in WCF.
A simplex connection is like sending a text message and then receiving a delivery notification - even though at a lower transport level there may be multiple calls between your phone and the carrier, from a communications level, you are sending the text message in one direction only.
A duplex connection is like making a phone call, you are able to send voice data to your carrier, and your carrier can send voice data in the other direction at the same time. This requires a simplex channel open in both directions.
Both ChannelFactory and DuplexChannelFactory can be used to create a client channel to a service.
Which one you choose is down to whether the service you are calling exposes simplex or duplex service operations, and whether you, as a comsumer, need to consume these operations.
If the service exposes normal (i.e, simplex) operations, for example:
void DoCoSomething(int x);
List<Things> GetThings();
etc...
...then you can consume these operations with ChannelFactory.
If the service exposes a callback contract:
public interface IMyDuplexCallback
{
[OperationContract(IsOneWay = true)]
void NotifyMeOf(string message);
}
for example, in order to send notifications or message of some kind to the consumers, and you as a consumer want to take advantage of this, you can use the DuplexChannelFactory to call the service (after implementing the callback contract on your client of course).
As a general rule, duplex communication in WCF is complex at best, and is therefore best avoided.
Appreciate this does not address your original question.

Categories