From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Actor Framework Documents

cancel
Showing results for 
Search instead for 
Did you mean: 

CS++LNAMessage.pdf

Proposal for Zero Coupling Linked Network Actor Messages.

Comments
drjdpowell
Trusted Enthusiast Trusted Enthusiast
Trusted Enthusiast
on

Hello, this is quite similar to my suggested solution at the end of this LAVA conversation: "Decoupling message based systems that communicate across a network"

Some things to consider:

1) one can use a text identifier instead of a class name, and have the receiver of the message (or higher-level calling code) define what actual command-pattern message should be generated.

1b) note that the sending process can handle message objects in flattened form without having the message class loaded in memory.

2) instead of variant attributes, one can pass an object (in my example, this is a "Data message" with "Read" methods rather than a "Do" method.

AristosQueue (NI)
NI Employee (retired)
on

Fire: Yes, this general vector is a good idea. There have been several variations along these lines suggested ever since drjdpowell first raised the idea. In particular, Powell's item #2 on his post above... avoids a fairly performance expensive conversion to/from Variant and maintains type safety throughout.

The fact that someone else had the idea doesn't negate your work -- a big part of the community development is seeing whether multiple people all end up at the same answer.

This is one of those community innovations that I would love to get spare time to work into the main AF trunk.

BrianGShea@NGC
Member
Member
on

Maybe, I'm really off here, but I just create two classes with the same exact name, one has an empty Do Method and is used by the sender to send a message with parameters. The other has only a Do that is linked to the targets method to be called. This is sloppy and requires two projects in separate folders but generally works.

Updating one messages requires that the other message be updated. So maintenance becomes a bit of a nightmare, but scripting can be used to generate one class from the other right?

Maybe a cleaner solution along these lines exists? I certainly don't like all the extra overhead of the proposed method, but could live with it.

Brian G. Shea
Certified LabVIEW Architect
drjdpowell
Trusted Enthusiast Trusted Enthusiast
Trusted Enthusiast
on

Hi Brian, Never thought of that.  But how do you handle multiple actors of the same type (multiple of the same hardware, say)?  You cannot have two copies to the same-named class with different Do methods.

BrianGShea@NGC
Member
Member
on

I don't. I never used it in that application. But I would guess if you placed each actor in it's own uniquly named library, that would allow different namespacing for each of the messages. Also, I would use an abstract actor class, a single actor class that defines all the methods as Dynamic Dispatch and create one set of messages that interact with the abstract version and allow dynamic dispatch to call the more specific hardware's method vi.

This would also cut down on the total number of message classes. I had posted a discussion about Abstract Actors, I've been so busy i have not been able to get good examples uploaded.

Brian G. Shea
Certified LabVIEW Architect
AristosQueue (NI)
NI Employee (retired)
on

drjdpowell wrote:


                       

Hi Brian, Never thought of that.  But how do you handle multiple actors of the same type (multiple of the same hardware, say)?  You cannot have two copies to the same-named class with different Do methods.


                   

You wouldn't need to have two different Do methods in this case.

For XYZ Message, you only need one XYZ Message class regardless of how many instances are created. The Do.vi of that message class does whatever the Do.vi says to do on the given actor.

You only need Brian's "two separate XYZ Message classes" solutions when the sender and receiver are on different targets -- one of the classes has an empty Do.vi because it will never be invoked. It does not matter how many copies of the actor are running in memory.

drjdpowell
Trusted Enthusiast Trusted Enthusiast
Trusted Enthusiast
on

I was imagining the case that you have, for example, sixteen copies of  “Temperature Control” actor all sending “Current Temperature” messages by TCP back to a central “main” actor.   “Main" has an altered version of “Current Temperature” with the “Do” method filled in.  But how does “Main” know which controller sent which message?  It can’t add any kind of metadata to the messages it receives.    What I’m really asking is: is the "two separate XYZ Message classes” solution powerful enough to solve multiple issues, or is it good for only one problem (code in the Do method)?

BrianGShea@NGC
Member
Member
on

The sender would need to provide the metadata to identify which instance of Temperature Controller sent the message. This would just be a required input on the Send Method. Otherwise, there's no way to identidy who the message came from, this goes for any solution that has multiple instances of the same actor spawned.

Brian G. Shea
Certified LabVIEW Architect
AristosQueue (NI)
NI Employee (retired)
on

I agree with Brian -- with this design, that's incumbent on the payload of the message.

Powell's alternate solution, using a flattened string, allows the receiver to provide a string to the sender, and the recevier might give a different string to each sender. That avoids putting it in the sender's payload, but it is still part of the message payload at some point.

drjdpowell
Trusted Enthusiast Trusted Enthusiast
Trusted Enthusiast
on

AristosQueue wrote:


                       

That avoids putting it in the sender's payload, but it is still part of the message payload at some point.


                   

Ah, but it's never part of the sender's codebase.  The sender does not need to be customized to the specific type of metadata the specific receiver requires, and thus is more reusable and simpler.

AristosQueue (NI)
NI Employee (retired)
on

Ah, but it's never part of the sender's codebase.  The sender does not need to be customized to the specific type of metadata the specific receiver requires, and thus is more reusable and simpler.


                   

Although I agree, it is a minor point to me. It isn't an undue burden for any actor to include its own enqueuer as an identifier in an outgoing message. It's going to do that for any other message that it needs an asynchronous response for, and its caller already has the enqueuer so it isn't sharing the refnum.

Essentially, I don't see there being a "specific metadata that receiver requires" in hardly any situations. There's a pretty standard way of representing the sender... I don't see reasons to not use it. At the beginning of the AF, we seriously discussed having the sender's refnum included in *all* messages so you could always track who sent a given item. We didn't do it, but it wasn't something I worried about from a burden-on-sender point of view, more it was a burden on just the size of the data.

BrianGShea@NGC
Member
Member
on

How does the sender know what temerature to read? At somepoint the sending actor has to know what IO point to read, whether it's a physical hardware channel, a modbus address, a user defined variable from an FPGA. At some point the sending actor must have some small piece of information to identify its specific behavior. This is the metadata that could be used to identify what temperature is reported by the message, and that metadata can be used by the receiving actor to process the incomming message and preform the correct action.

When i deal with classes that are spawned multiple times, whether is's an actor or just a standard class, i use a GUID (from C#). On embedded systems, the GUIDs are received from the host because the classes are initialized on the host and sent to the embedded system. Although the GUID generation code is fairly simple to create. I use a string to represent a GUID.

Brian G. Shea
Certified LabVIEW Architect
AristosQueue (NI)
NI Employee (retired)
on

Interesting variation, Brian.

drjdpowell
Trusted Enthusiast Trusted Enthusiast
Trusted Enthusiast
on

I guess my conceptual problem is that I don’t follow (in my “Messenger Library”) the AF design practice of mainly sending messages to Caller.  I expect to have a Caller launch subactors A and B, and register with A to send notifications to B, with the ability of the Caller to configure the message for B.  B doesn’t know A’s enqueuer or any other identifying information.  For example, the third of my 16 “Temperature Control” actors may be configured to send “Reading for Display" {plot name=“Main Furnace Temp”} messages to a UI actor, and “Temperature Reading” {sensor=2} to an {Safety Watchdog} actor.   The metadata {} is configured by the Caller.  This reduces the interdependency among the various subactors.

Contributors