Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Synchrounous Reply Message Example

Solved!
Go to solution

@PrimaryKey wrote:

I would recommend you have a look into this small example I wrote that makes it easier to build actors using subscriber publisher approach. 


Publish-Subscribe (aka Register-Notify) is a valuable messaging pattern in itself, but is not the same as Request-Reply.  Both have uses.  

 

In particular, be wary of sending a command, then trying to treat the notification that the command should generate as a "reply" to that command.  That is a poor substitute for a true reply, as other actions could generate the same notification.

0 Kudos
Message 11 of 24
(2,450 Views)

I'd like to throw in a second example of when a Request-Reply pattern would be nice to have. (Please note I'm a total noob to AF, so correct me if I'm trying to make an anti-pattern...)

 

If I have an actor controlling a piece of hardware (call it DAQ) and a main actor (call it Main), I need to have Main send a message "Initialize" to DAQ. At this point, Initialize could succeed or fail, and the next action of Main will depend on whether or not the Initialize succeeded or not. In other words, DAQ needs to reply to the specific "Initialize" method while Main waits on it. It would be tricky to just have DAQ send a message to Main after Initialize was successful; I would have to add more states to Main (like "Waiting on Initialization") that adds complexity.

 

An alternative solution is for Main to send a reply-queue along with the Initialization message, but I keep reading that you should only communicate between actors with AF messages, not with secondary message channels.

 

Anyway, after the Initialize is successful, Main could launch the "Logger" actor that connects to "DAQ" via Publish-Subscribe, but it seems to me that Main really needs a synchronous response.

 

Anyway, just wanted to throw a second example out there of when it may be beneficial.

Message 12 of 24
(2,438 Views)

@drjdpowell wrote:

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 second you introduce some payload to your "done" it gets complicated. E.g. "Do Job X" is "Measure Voltage". And you also habe many other Jobs such as "Measure Current", "Measure Peak-Peak", "Measure whatever" ... How do you publish this data? Either by introducing another channel (e.g. variables) or adding payload to your response. Now Worker needs to know a "Done" Message for each Request. That's where you start thinking about more generic messages ...

 

@PrimaryKey wrote:

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

That woule be one way to loop back my mesurements from above...

 

@BertMcMahan wrote:

I'd like to throw in a second example of when a Request-Reply pattern would be nice to have. (Please note I'm a total noob to AF, so correct me if I'm trying to make an anti-pattern...)

 

If I have an actor controlling a piece of hardware (call it DAQ) and a main actor (call it Main), I need to have Main send a message "Initialize" to DAQ. At this point, Initialize could succeed or fail, and the next action of Main will depend on whether or not the Initialize succeeded or not. In other words, DAQ needs to reply to the specific "Initialize" method while Main waits on it. It would be tricky to just have DAQ send a message to Main after Initialize was successful; I would have to add more states to Main (like "Waiting on Initialization") that adds complexity.

I do not have an answer, but that is exactly the origin of my initial question!

Whenever you have an API like Init-DAQ-Close (aka sequence) you need synchronous messages. A given solution is to introduce a proxy-pattern, but I have not seen an AF-Example.

 

Just to clear the air: All problems mentioned so far are clearly manageable somehow with the AF. But trying to stay completely async adds lots of overhead to simple things and the AF does not offer easy to use solutuions. A fully async "request and wait for response" (with timeout) would be cool which presents itself as a single vi (like dequeue element).

Thinking about this... that should be feasible ...

0 Kudos
Message 13 of 24
(2,425 Views)

The point behind actors is that each actor is responsible for himself. In your situation the Main should not care if the DAQ has successfully initialized because its the responsibility of the DAQ to take care of stuff like that. The only situation when DAQ should communicate its status to the Main is then it dies. Those situations you can handle with last ack. Other than that the Main should send jobs and not care what is the state of DAQ. The moment you start to mix responsibilities you loose the benefit of AF. 

DAQ should retry Initializing for N times before crashing and returning Last Ack to the Main caller.

The reason why Reply msgs should not be used is exactly this. When you use Reply msgs you introduce mixing of responsibilities. With generic events and subscriber/publisher this is mitigate with zero coupling.

Piotr Kruczkowski
Certified TestStand Architect
Certified LabVIEW Architect
Message 14 of 24
(2,420 Views)

As Piotr said, if you have a state machine in Main that depends on the actions of DAQ, then your system is incredibly tightly coupled.

 

One alternative (I'm currently trying this out) is to have my 'Measurement' class derived Actors have public messages only for things like Start and Stop Measurement, and then use the Send Stop Message for actually releasing/closing.

 

Within the parent Measurement class, the Start Measurement.vi checks an 'initialised' boolean and if false, calls a dynamic dispatch Initialise.vi. This isn't public - it's only called when you want to start the first time. 

 

One obvious potential problem here is that any connection difficulty is not found until you try to start measuring. If this is undesired, Initialise.vi can be called from Pre-Launch Init.vi.

 

A more difficult problem to work around is testing for these Actors, especially if I'm not careful about inheritance chains/layouts (read: it works if I don't do stupid things like make FakeDAQ a child of RealDAQ). Really, I need a DAQ class with shared, testable behaviour and then have Fake/Real only provide the specific hardware (or not) calls.

If FakeDAQ is a child of RealDAQ, and I set up item settings so each Initialise.vi must call parent, it's tricky not to get hardware calls in even the testing case. If you drop the must call parent, then you lose some control over Initialise.vi behaviour (in my case, it would completely break).


GCentral
0 Kudos
Message 15 of 24
(2,415 Views)

In situations where you want to optimize the communication i.e. only send a task to an actor B if he is ready, the only thing you should do is keep a local flag in actor A for the remote actor B. That local bit of information will tell actor A that actor B is in a specific state or not. This is updated by actor B sharing its status with actor A through normal msg, whenever something changes. This should still not be considered as safe, and precaution should be taken if the status flag is outdated or does not in fact mirror the actor B status. This kind of approach should only be used as an optimization mechanism, when not to do something and never as the only way to implement safety. The safety mechanisms should still be internal to actor B. In these situations there is always a trade-of between keeping the system asynchronous or breaking the paradigm and making it easy with blocking. I have not seen a situation where blocking would be the only solution.

Piotr Kruczkowski
Certified TestStand Architect
Certified LabVIEW Architect
Message 16 of 24
(2,403 Views)

@ChristophHS wrote:

The second you introduce some payload to your "done" it gets complicated. E.g. "Do Job X" is "Measure Voltage". And you also have many other Jobs such as "Measure Current", "Measure Peak-Peak", "Measure whatever" ... How do you publish this data? Either by introducing another channel (e.g. variables) or adding payload to your response. Now Worker needs to know a "Done" Message for each Request. That's where you start thinking about more generic messages ...

 


I see a couple of places in this conversation where posters have referred to an Actor "having" or "knowing" a message.  Note that an AF Actor, as a running process, is actually executing code in "Do.vi" methods that is not part of the "Actor" class itself.  So the fact that an Actor, as a process, needs to send a reply message, does not mean the Actor class needs to know anything about that message, as long as that message is sent from the "Do.vi" method of a received message.  With Request-Reply, this is a very natural setup, as I tried to illustrate with the email exchange.   The Request message, as part of its "Do" method, calls methods on the Actor object and builds and sends the Reply message (which can be a constant on the "Do" block diagram or be supplied as data in the Request message).

Message 17 of 24
(2,397 Views)

@PrimaryKey wrote:

In these situations there is always a trade-of between keeping the system asynchronous or breaking the paradigm and making it easy with blocking. I have not seen a situation where blocking would be the only solution.


Blocking Request-Reply is not against the Actor Model, itself.  Multiple other "actor" frameworks have blocking syntaxes (Akka has "ask"; Erlang has selective-receive).  Personally I think one should actually favour blocking to navigate what I call "system state transitions", simply and without experiencing potential race conditions.   I tried to illustrate this in a talk I gave at a CLA Summit: "Lessons of the subVI call in asynchronous programming".   

 

 

Message 18 of 24
(2,363 Views)

@drjdpowell wrote:


I see a couple of places in this conversation where posters have referred to an Actor "having" or "knowing" a message.  Note that an AF Actor, as a running process, is actually executing code in "Do.vi" methods that is not part of the "Actor" class itself.  So the fact that an Actor, as a process, needs to send a reply message, does not mean the Actor class needs to know anything about that message, as long as that message is sent from the "Do.vi" method of a received message.  With Request-Reply, this is a very natural setup, as I tried to illustrate with the email exchange.   The Request message, as part of its "Do" method, calls methods on the Actor object and builds and sends the Reply message (which can be a constant on the "Do" block diagram or be supplied as data in the Request message).


Oh, I like that idea. I had seen one or two places in my code where I thought doing a little more work in the Do.vi might be better than doing it in the actor's method. I hadn't considered that as a way to handle "receipts".

 

Instead of the caller sending "Acquire for 1 sec then say 'Done'" and assuming something is happening, a receipt message sent from Do.vi allows the caller to send "Acquire for 1 sec then say 'Done', OK?"

 

 

I've been avoiding that because it seemed needlessly complex.

0 Kudos
Message 19 of 24
(2,356 Views)

@auspex wrote:

I've been avoiding that because it seemed needlessly complex.


I would have thought that doing stuff in the "Do.vi" method of a message would be a standard way to program with the AF.   What do AF experts do?   Command-pattern messages are essentially a callback where the message sender can "inject" code into the receiver, without the receiver needing to be coupled to the sender.  This would allow the Actor object itself to be simpler and more reusable.

 

In "Messenger Library" my callback-like feature is the "Addresses" rather than the messages.  This is possibly not as powerful as the AF version but I do find it leads to simplification.

0 Kudos
Message 20 of 24
(2,329 Views)