LabVIEW Craft
  • Blog
  • About
  • Contact
  • Tools
  • Resources

Fun With the Actor Framework: Pub/Sub

11/3/2015

12 Comments

 
Jon McBee
Communication between Actors is meant to be done by traversing the Actor tree.  Assuming we decide not to pass message enqueuers around to all Actors in the tree, we will end up with a lot of message classes and a lot of message routing.  The extra messages and routing, however, buys us robustness as Actor E has no way of knowing if Actor C currently exists.  But what if we could bypass the tree for certain types of messages in a way that allowed us to decouple our actors from each other...
Picture
I'm going to start this post by saying that I am assuming you have some hands on experience with the Actor Framework, if you don't I suggest that you start here.  And you really should start, the Actor Framework is a powerful tool that will make it easier for you to write large, scalable applications.
Before diving in to the details, take a look at the video below.  It shows the Actor to non-Actor publish-subscribe in action.  It's 10 minutes long and starts off a little slow but give it time.
So what did we just see?  You may have noticed the mediator pattern popping up again, it made a showing in the last post as well.  I'm not going to go into detail on how it works (yet), but I do want to go into detail on how I used it in the video above.  This implementation is based on a presentation given by Dmitry Sagatelyan at the 2015 CLA Summit, I strongly encourage you to look through his presentation slides.
Picture
The first thing that I do is create a message broker, which is a by reference class that brokers messages between actors in a nicely decoupled way.  
Picture
Because the message broker is by reference I can branch its wire and safely inject it into Actors (and actors) before they are spun up.  Once the message broker has been created I register a data publisher for a data channel named "Test", this method outputs a message transport class.
Picture
Notice that I don't need to define a datatype for the data channel.  I am just creating the data channel and the message transport that will allow me to put data onto the channel.  Once the transport has been created, I can start publishing data on it.
Picture
Here is where I define the data type, package the named data into an object, and send it along its way via the message transport.  Notice the "Send" method icon shows that this message transport is based on the queue API.
Picture
I currently have 5 types of message transport but am tinkering with a few new ideas.  This post really only uses the queue message transport and the Actor Framework message transport.
Picture
Launching Actors looks like this.  The only thing different about this launch from a typical Actor launch is the "Set Message Broker Method".
Picture
Note that the "Set Message Broker" method is static dispatch and is a member of the Example Actor class.  I mention this because I want to call out that I made a design decision to use composition over inheritance to plug the Actor Framework into the mediator framework.  I could have made a parent Actor named Mediator Actor class and put the Message Broker object in its class data and given it a static method named "Set Message Broker" that its children could use, but I didn't.
Picture
On to the Actor side of the equation, looking at the project you can see that the Actor is fairly typical.  The only mediator-ish method in the class is the "Set Message Broker" method, which we saw above.
Picture
Here is the class data, you can see the Message Broker object.  The Transport object was added during the demo so that the Actor could publish data as well as subscribe.  The Transport object is created in the "Pre Launch Init" method.
Picture
There are three things I want to point out here.  The first thing to notice is that we are registering the Actor as a subscriber on the Test data channel.
Picture
The second thing to notice is that as part of the subscriber registration we are passing in an Actor Framework message transport that holds an Actor Framework Message object.
Picture
Take a look at the project again, this is a "Low-Coupled" message, meaning that it only implements the "Do" method, leaving the "Send" method to be implemented by a parent class.  If you want a refresher on low-coupled messaging take a look at this.
As a quick aside, I could have registered for this data with the Set Control Value Index message transport and sent the data directly to the gauge controls transfer buffer.
Picture
The class data for the Sample Actor Data Msg class is empty.  I figured I would show it in case you were curious.
Picture
Here is the "Do" method of the Sample Actor Data Msg class.  Notice that it is written to expect a message class of type DBL, and if it receives the wrong type it will pass out the expected types default value.
Picture
The third thing to notice is that we are registering the Actor as a publisher to the "Test" data stream, and storing the message transport object in the Actors class data.  This was added during the demo in order to give the Actor the ability to both publish and subscribe on the same data channel.
Picture
The last piece of the puzzle is the "Actor Core" method.  It is pretty standard with the exception of the publishing of data that was added during the demo.
As you can guess, there are some features here that bypass some of the built in safety of the Actor Framework.  There is also some room for some interesting innovation.  I think this is a pretty simple way to extend pub/sub to the Actor Framework, and because the publishers and subscribers are decoupled form each other we are able to do n to m pub/sub with Actors and non-Actors alike.  I find this stuff pretty interesting, I'm hoping that you do too.

Jon McBee is a Principal Software Engineer at Cambridge NanoTech and is a Certified LabVIEW Architect, Certified LabVIEW Embedded Developer, Certified TestStand Developer, an NI Certified Professional Instructor, and a LabVIEW Champion
12 Comments
Ohiofudu link
11/4/2015 11:20:24 am

Good Job .Can I get the Code as zip file to Play with.
Thanks

Reply
Jon McBee
11/4/2015 05:44:06 pm

Thanks! I am planning on getting this out, just working out the details of how and when. I will let you know once it's available.

-Jon

Reply
Mike King link
11/5/2015 02:03:45 am

Hey Jon, this looks very interesting. We've got a dispatch and transport layer for config and event objects, but I'm looking at what you have, and it may be a bit simpler to use and understand. Ping me as well if you publish this anywhere would love to take a close look.

Reply
Jon McBee
11/5/2015 07:31:39 am

Thanks Mike. I was aiming for simplicity, in the past I have written frameworks that grew too heavy to use and have seen others do the same. All of the mediator code is based on a presentation Dmitry Sagatelyan gave at the 2015 CLA summit, so I owe the lightness of this code to his ideas. Before I post this I want to write up a blog post on how it works and go through and add some documentation to the code itself. I also have a few ideas on usability tools that could make using this framework simpler and more powerful, I'd like to get those in before I turn it loose. Either way, I will be sure to ping you when I set it free.

Reply
Rob V.
6/17/2016 09:01:14 am

Hey Jon,
In your Sample Actor Data Msg.lvclass>>Do.vi I noticed you didn't pass out the class from the first "to more specific class". Any reason you have a second "to more specific class" doing the same thing inside the case structure for the actor and double class?

Reply
Jon McBee
6/17/2016 10:20:17 am

Hey Rob,

This is an Actor Framework trick, I can't claim credit for it. Here is the documentation for the trick from the AF, "The use of two To More Specific nodes, one with the output object unwired and the other with the error unwired, is a trick to avoid creating a copy of the Actor object while still preserving the original Actor object if the To More Specific fails."

Thanks
Jon

Reply
Rob V.
6/17/2016 11:20:12 am

Thanks for the breakdown Jon!

Jeff H.
8/1/2016 08:41:42 am

Hi Jon, Always fun to poke around on LabVIEW Craftsmen...

Regarding this entry, the demo video is not showing up for me and I know the code might be a little older but posting the source could help as well.

Thanks as always,
-Jeff

Reply
Jon McBee
8/1/2016 02:30:11 pm

Hi Jeff,

I'm not sure if I have that demo code in particular, but you can download the VI Package for the Mediator Pattern used in that example, and there is a better example VI built into the distribution. You can find that VIP here: http://www.labviewcraftsmen.com/tools.html.

Regards
Jon

Reply
Marco
9/1/2016 12:33:53 pm

Hi John,

I really appreciate your labview blog, especially the actor framework related examples.

I downloaded the Mediater Framework (1.0.0.6) from your tools section and quickly setup a simple three actor example. It works fine, but just FYI: the Websocket classes are missing some of their member VIs.

Anyway, nice work. Could you give us some examples, in which kind of situations you use this messaging framework rather than the standard AF task tree message routing?

Regards,
Marco

Reply
Ajay link
1/2/2018 04:11:55 am

Hi Jon.

This is nice article for a way to pub/sub in actors. I'm looking for downloadable source to have a deep look into it. Could you please let me know where I can download it?

Regards
Ajay

Reply
Christopher Culbreath
8/20/2018 01:07:20 am

Hi Jon,

Can you provide any insight as to why you chose to inject the message broker with composition rather than inheritance? You mention that it was a design decision, and I'm curious to know what factors influenced you to go this route.

Thanks!

Reply



Leave a Reply.

    RSS Feed

    Tags

    All
    Abstract Messaging
    Actor Framework
    Agile
    AI
    Asynchronous Programming
    Best Practices
    C#
    Complexity
    Continuations
    Control Values By Index
    Craftsmanship
    Dependency Inversion
    Dependency Viewer
    Futures/Promises
    Genetic Algorithm
    Liskov Substitution
    Malleable VIs
    Mediator Pattern
    .NET
    Object Oriented
    Object-Oriented
    Packed Project Library
    Parallelism
    Polymorphism
    Pub/Sub
    RawCap
    Root Loop
    Scrum
    Task Parallel Library
    TCP/IP
    TDD
    Test Engineering
    UML
    Unit Test
    VI Scripting
    VI Server
    WireShark

    Archives

    April 2019
    July 2018
    October 2017
    March 2017
    February 2017
    January 2017
    December 2016
    July 2016
    June 2016
    May 2016
    April 2016
    March 2016
    February 2016
    January 2016
    December 2015
    November 2015
    October 2015
    August 2015
    February 2015
    January 2015

    LabVIEW Blogs

    Eyes on VIs
    LabVIEW Hacker
    VI Shots
    LabVIEW Artisan
    Software Engineering for LabVIEW
    ​Wiresmith Techology
Picture
Powered by the Panda Ant

  • Blog
  • About
  • Contact
  • Tools
  • Resources