Replying...

Feb 7 at 3:18 PM
Edited Feb 7 at 3:22 PM

Hi,

I am giving a try to MiniBuss and I have 2 questions so far.

1. What is the point of the bus.Reply method (I mean if there is no method like "  var reply = bus.SendwithReply() " taking care of correlation between the messages) ? What the difference does it make with the bus.Send? 

2. Could we imagine following signatures on the IBus interface? 

void RegisterMessageHandler(Type typeOfCommand, Action<object> handler) ;
void RegisterMessageEndpoint(Type typeOfCommand, string targetEndpoint) where TCommand : class;

 

it looks like you cast Action<T> to Action<object> anyway and these signatures would facilitate implementation of an autoregistration mechanism 


Thanks,
Guirec

Coordinator
Feb 7 at 3:56 PM

Hi Guirec! Cool that you're giving MiniBuss a try!

1. The reason for the Reply method is mostly to get a nice programming experience I would say. It also gives you the chance to perhape easier control responses to specific commands. I'm not sure exactly what you are asking, but you can look at the sample code on this site.

2. You are right, but the reason the interface looks like that is that it makes it easier to write the code for the action because the command gets typed. With your suggested method interface for RegisterMessageHandler, you would have to cast the command object to use it in the handler code.

Now you can do:

bus.RegisterMessageHandler<HelloCommand>(command =>
{
    Console.WriteLine("Got command: {0} Guid: {1}, Number: {2}",
        command.Message, command.Guid, command.Number);
});

With your suggestion, one would have to do:

bus.RegisterMessageHandler(typeof(HelloCommand),cmd =>
{
    var command = (HelloCommand) cmd;
    Console.WriteLine("Got command: {0} Guid: {1}, Number: {2}",
        command.Message, command.Guid, command.Number);
});
 

It's not too bad, and it's very easy for you to make the changes yourself to the code if you like. Or add it to the codebase in a partial class with something like this (not tested ;):

public partial interface IServiceBus
{
  void RegisterMessageHandler(Type typeOfCommand, Action<object> handler);
  void RegisterMessageEndpoint(Type typeOfCommand, string targetEndpoint);
}

public partial class ServiceBus : IServiceBus
{
  public void RegisterMessageHandler(Type typeOfCommand, Action<object> handler)
  {
      _messageHandlers[typeOfCommand] = handler;
  }

  public void RegisterMessageEndpoint(Type typeOfCommand, string targetEndpoint)
  {
      _targetQueues[typeOfCommand.TypeHandle] = GetEndpointName(targetEndpoint);
  }
}

Question for you - you mentioned autoregistration. Can you explain a bit more what you had in mind? Sounds interesting because I have some experimental code which does just that.

 

 

 


Feb 8 at 2:30 PM

Hi,

Thanks for your answer.

Feedback after testing:

  • It all works fine !
  • I like the lean concept : no app/web .config stuff, just code.
  • I have a few things that I'd like to see/have/discuss/share ;-) 

So, the way I'd like to use minibuss to send is : 

ServiceBus.Current.Send(anyObject, destination);

There would be no need to register destination endpoints anymore and it allows to send multiple messages of the same type to different recipients. With actual implementation I feel like if my post office is sending all my love letters to my first girlfriend ;-)

As you've noticed I'd also like to access the bus with a singleton. It's much more practical than having to expose the instance by myself somewhere in the application. You'll tell I could use an IOC container but I am too old to change now.

 

The way I'd like to use minibuss to receive is:

ServiceBus.Current.Endpoint = "myqueue";

and that's it. This should be sufficient to setup the queue, auto-register the command handlers and start peeking. 

To make this possible we should have an interface like : 

public interface IHandleMessage<T>
{
	void Handle(T message);
}

Then, before starting, the bus could discover handlers automatically. T should not be constrained to be a class but could be an interface : better for decoupling. 

Another implementation details: Minibuss actually suppose we only have one handler per message type. There is no reason we would not like to have multiple handlers. If someone sends a message saying house is on fire it is better if everyone can catch it, rather than just one guy who would have to dispatch the message on its own mean.

 

Then same principle could apply for Publish/Subscribe with:

ServiceBus.Current.Publish(anyObject);

and

public interface ISubscribeTo<T> : IHandleMessage<T>
{
	string PublisherQueue {get;}
}

 

Johan, that's my 2 cents.  

Coordinator
Feb 8 at 3:06 PM

Thanks for the post! Again, I think it's about programming style and I think it would be pretty easy to create a Singleton-wrapper around the ServiceBus code with the Send method etc. I understand what you are looking for :)

The IHandleMessage style of coding looks much like nServiceBus, doesn't it?

You are right about the one handler per message type, that's the way it's designed, with a dispatcher. But I don't really understand that last interface. Could you explain your thoughts i bit more, perhaps with some dummy/sample calling-code? (I'm in a bit of a hurry and perhaps reading your post a bit too fast ;)

Cheers,

Johan

Feb 9 at 8:57 AM
Hi Johan,

I am not well versed in nServiceBus, so I can't really tell. I looked at it very quickly and it is definitely too big for my needs. The Saga part looks really interesting if you need a 'true' bus.
In my scenario I just need a push and forget functionality that's why I am interested in something very lean with no config.


I customized the code to my need and now my publisher is as simple as :
        static void Main(string[] args)
        {
            var bus = ServiceBus.Current.LocalEndpoint = "ConsoleApplication1";
            ServiceBus.Current.Send(new Command { Id = 1, Text = "Do Work !" }, "ConsoleApplication2@localhost");
            Console.ReadKey();
        }
basically it is one line to start the bus with no configuration on endpoint as I specify them when sending (Gives me more flexibility)
My receiver is the same:
        static void Main(string[] args)
        {
            ServiceBus.Current.LocalEndpoint = "ConsoleApplication2";
            Console.ReadKey();
        }

here is my Command object (it inherits BaseCommand which implements ICommand)
    public interface ICommand
    {
        int Id { get; set; }
    }
 
    [Serializable]
    public class BaseCommand : ICommand
    {
        public int Id { get; set; }
    }
    
    [Serializable]
    public class Command : BaseCommand
    {
        public string Text { get; set; }
    }
now on the receiver side I added some handlers (which are discovered and auto-registered when I set the local endpoint )
    public class CommandHandler : IHandleMessageOfType<Command>, IHandleMessageOfType<BaseCommand>
    {
        public void Handle(Command message)
        {
            Console.WriteLine("CommandHandler 1: I took #{0} because it is a Command", message.Id);
        }
 
        public void Handle(BaseCommand message)
        {
            Console.WriteLine("CommandHandler 1: I took #{0} twice", message.Id);
        }
 
    }
 
    public class CommandHandler2 : IHandleMessageOfType<Command>
    {
        public void Handle(Command message)
        {
            Console.WriteLine("CommandHandler 2: I took #{0} because it is a command as well", message.Id);
        }
    }
 
    public class CommandHandler3 : IHandleMessageOfType<BaseCommand>
    {
        public void Handle(BaseCommand message)
        {
            Console.WriteLine("CommandHandler 3: I took #{0} because the message inherits from BaseCommand", message.Id);
        }
    }
 
    public class CommandHandler4: IHandleMessageOfType<ICommand>
    {
        public void Handle(ICommand message)
        {
            Console.WriteLine("CommandHandler 4: I took #{0} because the message implements ICommand", message.Id);
        }
    }
as you can see a handler can handle several kind of messages (case of CommandHandler) and can as well subscribe to any interface or base class of the command.
When I send my message from my publishing application I expect all handlers to receive the message and it does!

Coordinator
Feb 9 at 9:42 AM

Yes, I see. Very cool! Would you like to create a zip of the code and sample and send me? I could try to add your code to a "MiniBussExtensions" project I'm working on. I would of course give you full credit for the work!

You can reach me at johan.danfort at irm.se

Best regards, Johan Danforth

Feb 9 at 1:03 PM

Just tried to send you the code but I have a "technical failure" response...

Coordinator
Feb 9 at 1:08 PM

sorry I can't seem to spell my own name correct, it should be johan.danforth at irm.se (danforth with an 'h' ;)

/Johan