Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Synchrounous Reply Message Example

Solved!
Go to solution

Dear all,

 

is there an example for "Send Message And Wait For Response" available?

Am I supposed to manually extract the reply queue from "Reply Msg" and write my variant data to it?

Here's "Send VI And Wait For Response". I have no Idea why the wire is broken in the snippet, it's fine in my VI.

sn.png

Regards

Christoph

Message 1 of 24
(7,204 Views)
Solution
Accepted by topic author ChristophHS

Ok I got it ... apparantly you're supposed to inherit from "Reply Msg" overwrite "Do Core" !?

There is no automatic message creator for that kind of Msg ? I really do like the AF but the complexity or the level of abstraction (and the number of VIs) is a pain ...

 

I uploaded my test on GitHub : LabVIEW-AF-Synchronous-Message-Example

 

0 Kudos
Message 2 of 24
(7,188 Views)

@ChristophHS wrote:

Ok I got it ... apparantly you're supposed to inherit from "Reply Msg" overwrite "Do Core" !?

 

That is correct.  Then you use Send Message and Wait for Response to actually send the message.

 


There is no automatic message creator for that kind of Msg ? I really do like the AF but the complexity or the level of abstraction (and the number of VIs) is a pain ... 

Reply messages are intentionally obfuscated, because they break asynchronicity, i.e. they inject synchronous behavior into our asynchronous systems.  This can cause deadlocks and other real headaches down the road if you aren't very careful.  There are some instances where they are necessary, but those instances seem to be limited to moving between actor space and command/response spaces like web services.  Chances are, if you think you need a reply message between actors, there is probably a better way.

 

So, no tool support.  You shouldn't ever need enough for hand-crafting them to be a deal-breaker, and making you do so helps keep the total count down.  I was the biggest advocate for including reply messages, and in all my time working with AF, I've only ever needed one once.  That was with a web service.

 

Which leads to the other reason there is no tool support:  the one time I needed one, I needed a slightly different form.  The shipping reply message should best be viewed as a reference architecture.  Study it, use it if it works for you, and roll your own if it doesn't.  If you roll your own, be sure to override Drop Message Core.vi.

 

We do cover Reply Messages in the course (Actor Oriented Design in LabVIEW), in the chapter on including actors in synchronous systems.  That ensures that there is a live instructor who can take your questions, try to drive home how rarely you should use these, and make sure you can protect yourself when you do.

Message 3 of 24
(7,159 Views)

Thank you for your detailed reply.

 

@justACS wrote:
Reply messages are intentionally obfuscated, because they break asynchronicity, i.e. they inject synchronous behavior into our asynchronous systems.

This can cause deadlocks and other real headaches down the road if you aren't very careful.  There are some instances where they are necessary, but those instances seem to be limited to moving between actor space and command/response spaces like web services.  Chances are, if you think you need a reply message between actors, there is probably a better way. 

I do understand the nature of the problem. However I have troubles how to properly implement an asynchrounous "Request / Response" with an actor design.

 

What I have seen so far is a asynchrounous request (aka message) and actors that simply publish information globally (shared variables etc.). It is up to the requesting side to get  the data of interest.

 

That's where the problems arise: If you force your application to always hava a known relation like 1:1 you might geht along.

My understanding of a low coupled system like this is that - during design - it should not matter if an entity aka. actor is part of a a 1:1,  n:1 odr 1:n relation.

So the approach of publishing data does not scale well unless you publish every data of interest (e.q. the response to a request) with an unique identifier to help the requesting side identify a relevant reply. Otherwise caller does not know if your request has been processed.

 

You may go for asynchrounous response message by making callee reply (async) to the caller.

That does solve the issue of identifying your response and removes globally publishes data. However this adds the overhead of specific reply message to every request and caller has to handle it async. At this point you may go for simplifying the asynch request/response by introducing more generic messages, which imho just obfuscates the problem. And you still have to manage pending replys on caller sinde somehow.

 

What I want to say: I do understand the dangers of deadlocks, but this does add a load of complexity and overhead.

 

So how to implement a straight forward simple request/response (or command/ack etc.) remains a mystery to me.

0 Kudos
Message 4 of 24
(7,150 Views)

Does the AF not have a standard Async-Request-Reply implementation?  Having one would guide people away from using the Synchronous version in cases where blocking is not needed.

0 Kudos
Message 5 of 24
(7,135 Views)

If I've understood properly, the asynch request-reply method would be to have the Actor who supplies the information (A) define a Self Addressed Message inheriting message, with private data for the element(s) to be sent, and accessor methods to write and read those elements.

 

Actor B can then create a SAM of that class and send it to A, who can process it at leisure and then return it to the address in the message. A doesn't need to know anything about B, but B needs A's queue and access to the message class for this.

 

I don't know of an automated way to create such a message though.


GCentral
0 Kudos
Message 6 of 24
(7,129 Views)

I'm using an abstract message. I'm making a side project to demonstrate this, but it's not ready yet. Here's a sketch.

 

I have multiple Sources, an Aggregator, a Mediator, multiple Requestors, and multiple Sinks.

 

The Mediator is the root actor. It launches the Aggregator and the Requestors.

The Aggregator launches the Sources.

The Requestors launch their Sinks.

 

The Sources are of a class that has an abstract message Reply. This is provided as an argument to the class's concrete message Request. The Sources send the Reply message to their caller with the concrete type provided by the caller. As already described, the caller is the Aggregator, but it doesn't have to be. The caller need only send the Request with the Reply it expects.

 

The Aggregator can wait for all its Sources, or any subset of them. Its implementation of Reply adds replies to a pool. When the pool is full, it puts the data from the Sources into a Reply from its caller, the Mediator, and sends it along. The Aggregator is actually a type of Source.

 

The Aggregator's concrete Reply message can contain an index to keep data sorted in the order it was requested from Sources. It can be keyed so that multiple requests don't get mixed up. Its role really is to synchronize the Sources.

 

The Mediator is the only actor that doesn't reply to its caller, because it doesn't have one. Instead, it receives a Reply message from one of its nested actors, i.e. the Requestors. But which one? One option is to ignore which one and send the Reply to all the Requestors. Nothing will happen at the Requestors that didn't make the request, because the Reply message will be the wrong type. Another option is to somehow provide the Requestor's enqueuer to the Mediator. There are at least two ways to do this.

 

One is for the Mediator's Request message to require an enqueuer reference. Any Requestor will then include it's self-enqueuer reference with the request.

 

Another is for the Mediator to provide each Requestor with a different Request type.

 

Not an option--or not an easy one, alas--is for the Mediator to provide a Request type containing the Requestor's enqueuer. The Mediator won't have the enqueuer until after launching the Requestor, so it cannot just write the type to the Requestor; it would have to send it in a message, which the Requestor would have to process, so it's just as well to make any Requestor always include its self-enqueuer reference.

 

Indeed, it is an option to always have the Request include not only the Reply type, but the enqueuer to reply to. Actors in the middle of the request path could then cut themselves out of the reply path. I'm not sure that's a good idea, but I may try it.

 

The Requestors then process the data and send it on to their Sinks. Nothing special here: the Sinks are just log files, data files, etc.

 

0 Kudos
Message 7 of 24
(7,111 Views)

Happy new Year and sorry for not replying earlier.

 

@drjdpowell wrote:

Does the AF not have a standard Async-Request-Reply implementation?  Having one would guide people away from using the Synchronous version in cases where blocking is not needed.

I would not know about any standard. Imho thats up to you. The question is more about how much coupling you want in your project. It's always a possibilty to hard code requeste and responses by sending known messages, however as mentionend above you soon find that to be too restrictive (and too much coupling). That's where abstract messages or generic messages come in handy...

So yes you might call that a "standard" implementation however that does not solve the issue of synchronzing a response to a request.

 


@auspex wrote:

I'm using an abstract message. I'm making a side project to demonstrate this, but it's not ready yet. Here's a sketch.

 [...]

That sounds interesting and I would like to see a demonstration at some point.

However what you're doing is reimplementing some message-broker (mediator) based system. That's cool if that's what you want. But most certainly not an utmost simpyfied solution to a simple sycnchronized request-response pattern. However I'm looking forward to that demo. Btw. you might want to check out ZMQ, there are also LabVIEW bindings available. Don't know if that's something for you, but at least interesting to read about their "sockets" aka message-patterns.

 

But maybe it's getting a bit off topic now ...

0 Kudos
Message 8 of 24
(7,059 Views)

@ChristophHS wrote:

Happy new Year and sorry for not replying earlier.

 

@drjdpowell wrote:

Does the AF not have a standard Async-Request-Reply implementation?  Having one would guide people away from using the Synchronous version in cases where blocking is not needed.

I would not know about any standard. Imho thats up to you. The question is more about how much coupling you want in your project. It's always a possibilty to hard code requeste and responses by sending known messages, however as mentionend above you soon find that to be too restrictive (and too much coupling). That's where abstract messages or generic messages come in handy...

So yes you might call that a "standard" implementation however that does not solve the issue of synchronzing a response to a request.

 


Request-Reply is a messaging pattern that is naturally "low-coupling", in that the Replier doesn't need to know anything about the Requester.  Consider this email Request-Reply:

 

To: Worker

From: XYZ

Subject: Do Job X

 

To: XYZ

Subject: Re: Do Job X

Body: Done

 

In this case "Re: Do Job X" is a command for XYZ, that is specified by XYZ, not by Worker.  In the AF, the Worker Actor need only specify a "Do Job X.vi" method (which returns a "Done" boolean if the job was done).  Everything else in a Request-Reply interaction can (and quite naturally should) be set only be the Requester Actor, which should provide both the address and reply message class in the original request message.  There is no need that I can see for any kind of abstract or generic message classes; just two simple messages defined by the Requester.

 

The basic AF messaging pattern is just Command: send a command.   But just because on receiving a Command one sends another Command "back" is not the same as Request-Reply.  One replies to a request, and the request is a message.   Two-way Commanding would lead to high-coupling, since then both parties need to know the command set of the other, but Request-Reply is a naturally low-coupling pattern, as the Replier needs know nothing about the Requester.

 

So I think the AF could do with an Async Request-Reply implimentation.  

 

Message 9 of 24
(7,045 Views)

I would recommend you have a look into this small example I wrote that makes it easier to build actors using subscriber publisher approach. 
https://forums.ni.com/t5/Actor-Framework-Documents/Event-Source-Actor-Package/ta-p/3538542

Piotr Kruczkowski
Certified TestStand Architect
Certified LabVIEW Architect
0 Kudos
Message 10 of 24
(7,042 Views)