tying to message oriented middleware

19 views
Skip to first unread message

gminorcoles

unread,
Feb 6, 2009, 7:27:15 AM2/6/09
to retlang-dev
Hi,
I came to find the retlang project in kind of a backwards fashion.
I wanted to find a .Net-based ESB and retlang was mentioned on some
blogs in comparison to some of these ESB frameworks. One blogger
speculated that one could somehow wire up retlang with some
distributed messaging software and acheive something that looked very
similar to an ESB.

Does anyone have an opinion as to whether such an integration would be
worthwhile? I have not even evaluated retlang yet. What advice would
you give as to exactly what the best integration points would be
between retlang and something like activemq or MSMQ?

Also, is retlang .Net 2.0 friendly?

thx
George

Mike Rettig

unread,
Feb 6, 2009, 11:36:06 AM2/6/09
to retla...@googlegroups.com
Retlang is best used as a unifying threading model for highly concurrent applications. In normal usage, I write adapters that receive messages from other messaging systems (activemq, plain tcp, msmq, etc), then publish the messages over channels to a Retlang Fiber for applying domain logic. Incoming messages arrive on the receive thread of the middleware. This thread translates from the external format (typically a plain dto) to an internal message. The internal message is published on a channel to the Retlang Fiber(s) for processing. The fiber generates new events that are sent over channels back to a send thread that translates the internal message to the external form and writes to the middleware. 

The pipeline looks something like this:

Inbound  -> Channels -> Fiber   -> Channels -> Outbound 
Msmq                                                    Msmq
ActiveMq    ----------> Retlang ----------->      ActiveMq
Tcp                                                        Tcp
Udp                                                        Udp

Many people attempt to place the domain logic on the receive thread of the middleware. This may work in simple cases, but breaks down when the domain objects receive updates from other sources that are not on that same thread. As a simple example, the app may need to publish data on a regular interval. The timer thread and the middleware updates will need access to the same data. This can be painfully solved with locking, but a better solution is to adopt an internal pipeline using Retlang to decouple the domain logic from the middleware threads. 

Retlang guarantees that the events are delivered in order, and as long as all events pass through the Fiber, no locking will be required.

Mike

Mike Rettig

unread,
Feb 6, 2009, 11:37:39 AM2/6/09
to retla...@googlegroups.com
The most recent version 0.4+ is built with 3.5 while 0.3+ used 2.0.

Mike

On Fri, Feb 6, 2009 at 6:27 AM, gminorcoles <gmino...@gmail.com> wrote:

gminorcoles

unread,
Feb 7, 2009, 10:29:38 AM2/7/09
to retlang-dev
Thanks for the succinct explanation.

On Feb 6, 11:37 am, Mike Rettig <mike.ret...@gmail.com> wrote:
> The most recent version 0.4+ is built with 3.5 while 0.3+ used 2.0.
> Mike
>

gminorcoles

unread,
Feb 17, 2009, 10:12:38 AM2/17/09
to retlang-dev
I have some further questions, I hope you don't mind. Your library
seems easier to use than the CCR for example but while your outline
above was clear enough conceptually I would appreciate it if the code
below does what you intended. This is the step that hands off the
object from the middleware (rabbitmq in this case) to internal
subscribers. ProcessMessage cracks the message and calls
channel.publish(). OnNewData is an event whose delegate is generically
typed. This will probably be slow but I am still figuring out how to
reuse all this code in a way that cleanly specifies the message
payload type and requires not much rewriting by different clients.

using( internalPublisher = new ThreadFiber())
{
internalPublisher.Start();
Retlang.Channels.IChannel<IncomingType>
retlangChannel = new Channel<IncomingType>();
retlangChannel.Subscribe(internalPublisher,
delegate(IncomingType obj){
if( OnNewData != null )
{
OnNewData(obj);
}
});

Console.WriteLine("Consumer tag: " +
sub.ConsumerTag);
foreach (BasicDeliverEventArgs e in sub)
{
ProcessMessage(e,retlangChannel);
if (Encoding.UTF8.GetString(e.Body) ==
"quit")
{
Console.WriteLine("Quitting!");
break;
}
}
Console.WriteLine("out of messaging loop");
Reply all
Reply to author
Forward
0 new messages