Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Sending a message to an actor (not from the caller) and sending a return message

I'll admit I haven't looked closely enough through all the AF stuff, but I did try and I am pressed for time, so I figured I would ask.

I want to send a request to an actor and then send a reply back. This doesn't have to be synchronous. I'm willing to get the reply later.

The "using the AF" document has the following to say:

The actor object has a method called Get Queue For Sending To Caller.vi which Do.vi can invoke to return data to the caller. This assumes, of course, that the message came from the caller originally. If the original sender was not the caller, the sender may provide an instance of Self-Addressed Message in the original request to use for the reply.

So that seems to indicate that the SAM is the way to do this, but after looking at the SAM VIs I can't figure out how this is supposed to work and I haven't seen any examples. Can anyone put together a simplistic example demonstrating this?

I could do this on my own by sending the queue reference as part of the message, but if it's built-in, I would rather use that.


___________________
Try to take over the world!
0 Kudos
Message 1 of 15
(15,351 Views)

> I could do this on my own by sending the queue reference as part of the message, but if it's built-in, I would rather use that.

I'm going to recommend that you do that. We do not have any examples of SAM, and I have found that it is less work to package the reply queue into the original message than to use SAM. SAM really doesn't have any way to send a reply back to to the original address -- it just sends the pre-packaged message, so the best you can communicate is "I'm done", but not any status about what was done. To add payload to that response is problematic... I found that it was only really worth doing if you had a caller actor with a dynamic number of nested actors of all the same type. For anything else, just packaging the queue into the original message and then doing the same things you would to send any message seems simpler.

PS: Note that one of the other main AF devs may have a different answer for you. I was not the developer for that class, and I know that the others find it valuable. Whether or not they find it valuable in the same dynamic-multiple case that I do is something I haven't really talked to them about.

0 Kudos
Message 2 of 15
(5,379 Views)

tst,

I apologize that I do not have an example handy, and, to be honest, I have not used this feature yet but I do know the AF.  Since you seem to be in a hurry perhaps I can shed a little light on the subject...

Let's assume you have a message called OpenDoorMessage that will be sent from ActorA to ActorB. When you send it to an ActorB, you want ActorA to get a reply at some point that the door opened, that would be called the DoorIsOpenMessage.

The OpenDoorMessage would need a Self-Addresssed Msg object as part of its class private data.

Use the AddressMessage.vi to assemble a Self-Addressed Msg by supplying the queue of ActorA and a DoorIsOpenMessage.  Wire the output of Address Message.vi to the 'Write Self-Addressed Msg' property of your OpenDoorMessage.

In the Do.vi of the OpenDoorMessage, simply take the Self-Addressed Msg stored in the private data of the message and wire it to the Send Self-Addressed Message.vi.

I think that is it.

As an aside, you can have the reply go to any Actor not just the sender.  You would do this by setting the 'Target Queue' of Address Message.vi to something different than the sending actor.  Also, this assumes in the scenario above, the door actually does open and the fact that you get a DoorIsOpenMessage is really accurate.  You could supply two 'reply' messages - one for success, one for failure.

Hope this helps.

Kurt

AQ - you are too fast! And I would probably just send a queue along in the message if I really needed this kind of reply mechanism.

0 Kudos
Message 3 of 15
(5,379 Views)

Ah, I see. I was thinking of attaching some custom payload to the reply message and it doesn't look like this will work for that, because you have to build the message in the original sender. Basically, the idea is that A sends an "I want you" message to B and B says "nope, C already has me" or "hey everyone, A has me".

I think what I'm going to try is creating a mid-level  "actor with reply event" (which I'll inherit from) and have each actor register for that event and process the messages it expects (the reason I'm thinking of an event is that I might want to send the messages to multiple destinations and some of them might not be actors). The advantage is that you code it once (the event ref is created in the actor's init code) and you expose a register VI which you call before sending the message. I don't know if this design is robust enough, but I guess I'll find out.


___________________
Try to take over the world!
0 Kudos
Message 4 of 15
(5,379 Views)

Tst: I have considered building a modified version of Reply Msg that instead of using a synchronous queue uses the original queue that it was sent on. Thus the existing "Reply Msg" is actually "Synchronous Reply Msg" and this new one would be "Asynch Reply Msg". I haven't needed it in my current work, but I've got a project at home where I think that would be useful.

0 Kudos
Message 5 of 15
(5,379 Views)

I just wanted to clarify for folks reading this post, that out of context, tst's quote from the AF documentation is kind of confusing.  It is not the fault of tst, just the naming convention used in the documentation and the intent of the AF.

The actor object has a method called Get Queue For Sending To Caller.vi which Do.vi can invoke to return data to the caller. This assumes, of course, that the message came from the caller originally. If the original sender was not the caller, the sender may provide an instance of Self-Addressed Message in the original request to use for the reply.

The term 'caller' refers to the Actor that launched the actor that received the message.  So, Get Queue For Sending To Caller.vi will return the queue that was suppplied to the 'Actor-To-Caller' terminal of Launch Actor.vi.  There is no built in mechanism that provides the queue of the Actor that enqueued the message (ie the sender).  If you want to carry this along, you would have to add this to the private data of derived messages and, of course, set this prior to sending.

Message 6 of 15
(5,379 Views)

tst,

What you describe is like an observer pattern implemented with user events.  While I think it is doable, you might loose some of the features built into the AF queue structure, namely message priorities.  The subject actor would have to keep track of the observer actor queues and there is a sequential broadcast of a message unless you build in some sort of synchronization mechanism before the actual enqueue.  (hmm, something I might want to look into on my stuff)

I have no technical reason that I would not use events, I have just not shared events between actors yet.  Within process loops of an actor I have done this, but the process loops typically have had a UI component to them.  I know that I will eventually want to communicate with actors that are either running under another application or on another computer and I know that AF will eventually support this feature.  So the more layers I add on regarding inter-actor communications, the more issues I expect to have in the future.

Kurt

0 Kudos
Message 7 of 15
(5,379 Views)

I have a reason not to use events: sharing *any* refnum between actors other than the queues exchanged by Launch Actor.vi creates shutdown timing race conditions and should be avoided. We've had several issues arise from people trying to layer a new communications channel onto the AF, some of which are discussed in the forums. It's a bad idea.

You can use events (or other refnum types) *within* an actor. But not between them.

We do this with the Reply Msg, sharing the internal queue, but that works because of the limited nature of the refnum -- the caller, who created the refnum, cannot proceed until that reply comes back or the queue gets destroyed, and the message is guaranteed to be either replied to or destroyed (in Drop Message) by the framework.

Sorry... I should have mentioned this earlier... I saw your "Message with reply event" and in my head just assumed you were using "event" in its generic meaning for "I'll trigger you when I've got the reply ready", without really thinking that you meant "I'll share an event refnum".

0 Kudos
Message 8 of 15
(5,379 Views)

Kurt Grice wrote:

What you describe is like an observer pattern implemented with user events.

You're right. I was getting too bogged down in the implementation details of the AF to notice. I will have to decide whether this is the architecture I want or not.

AQ, I don't think the shutdown race conditions would be an issue here, because the observers only rely on the observed at some point in their execution, not for shutdown. Not getting a notification from the observed is a legitimate case. In any case, I've seen some of the other discussions now and I will have to decide how to proceed.


___________________
Try to take over the world!
0 Kudos
Message 9 of 15
(5,379 Views)

Kurt Grice wrote:

tst,

What you describe is like an observer pattern implemented with user events.  While I think it is doable, you might loose some of the features built into the AF queue structure, namely message priorities.  The subject actor would have to keep track of the observer actor queues and there is a sequential broadcast of a message unless you build in some sort of synchronization mechanism before the actual enqueue.  (hmm, something I might want to look into on my stuff)

I have no technical reason that I would not use events, I have just not shared events between actors yet.  Within process loops of an actor I have done this, but the process loops typically have had a UI component to them.  I know that I will eventually want to communicate with actors that are either running under another application or on another computer and I know that AF will eventually support this feature.  So the more layers I add on regarding inter-actor communications, the more issues I expect to have in the future.

Kurt

I've developed a different actor-like framework where I use the Observer Pattern and pass messages over tcp.  The key is to use the actor's message queues themselves to pass event messages, rather than use a separate communication path like a User Event.  One actor registers its own queue to receive event messages from another actor.  The actors that publish events use a third helper actor called "Observer Register" to keep track of all the observer queues.  Because only the main message queues are used, this doesn't add excessive complexity when working over a network.

-- James

0 Kudos
Message 10 of 15
(5,379 Views)