Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Web Service & Actor Framework

Probably a side topic for another thread, but for some of my systems lately I've had good success using JSON-RPC to expose a cRIO to a remote host.  The use case I'm going after is essentially taking a system that would previously be controlled via serial commands and moving to an ethernet-based control architecture.  For these systems, going with the example above made sense, but of course may not make sense for a different kind of system or use case.

mtat76 wrote:

This is an interesting architecture issue.  I feel that if you are using web services, the web service should not be depending on information that is not initiated via an http request.  That is, if you want to move the controller, send the command using http GET.  If you need to know the current position, the view portion of the application should be polling at regular intervals for a data packet that contains that current position.  Ultimately, the two requests are independent of each other.  I don't believe that Eldon's intent is to adjust the http status code response based on the device response; so ultimately all  the requester should care about is 1) whether the service is alive and 2) no error was thrown when the request was handled and forwarded.  The state of the component that ultimately handles the request (i.e. the underlying model) should be maintained by the model itself and be part of the data stream that is returned to the controller in charge of aggregating system information.   

Cheers,

Matt Pollock
National Instruments
0 Kudos
Message 11 of 21
(1,589 Views)

Matt,

The problem with the DVR approach is that it does not work with a class structure. Most of the information that is being returned is encapsulated inside of the class that the root Actor owns. I could make it a global but I prefer not to use them unless necessary.

I have been programming for many years but have found that the Actor Framework has some functionality that I need, and have created before, so I am trying to use it. In trying to use something new, I try to understand the intent of the developer so as to stay inline with how the developer intended the tool to be used. You can modify anything to make it work the way you want it to but this is not necessarily the best approach.

As far as the Send Message and Wait for Response, there are many discussions on this forum about using this functionality. It exists but its use is not encouraged.

Later,

Eldon

0 Kudos
Message 12 of 21
(1,589 Views)

Matt,

It is an interesting problem. I could solve it by just programming it the way I feel it should be done but I am curious as to what others suggest.

The http "Get" needs to return data and a status code. If the controller is not responding then the status code needs to reflect this.

With the Web Service and the Actor being seperate processes, it becomes a communication problem. There has been much discussion about using the Actor Framework as a receiving message center only. If a response is needed, have the framework send a message back to the calling framework with the information. This does not work with the Web Service unless sometype of response queue is implemented. This falls back to using the Send Message and Wait for Response.

So, is this the case that breaks the rule or is there a better solution?

Later,
Eldon

0 Kudos
Message 13 of 21
(1,589 Views)

This comment I really don't understand -  "Does not work with a class structure"?  This is just memory space.  It works with everything.  I would strongly encourage you to look at other OO solutions such as the extensible session framework - an extremely powerful yet simple framework - or Jonathan Green's error logger - which won an award - that make extensive use of DVRs.  Anytime you require some type of singleton pattern, you are likely going to be using a DVR or something similar.

Ultimately, web services run in a different space than your main application and therefore you will need some way to communicate with them.  This will be some type of memory space - a queue, a DVR, a global, an FGV etc. etc.  There is no getting around this.  In my applications, I have generally stored references to actor queues held by a single controller in an FGV and data that is maintained by the controller for portions of the service that require them.  This means that updated data is always available and the web service contains the means for forwarding messages to the proper portion of the application.  In this way, I consider my web services to be a piece of the controller (although they truly aren't) and can utilize the data in the controller and directly communicate with nested actors.  This doesn't break the AF paradigm as web services are not part of the AF; it is just one solution to the communication issues associated with using web services in an application.

Cheers, Matt

0 Kudos
Message 14 of 21
(1,589 Views)

Eldon wrote:

As far as the Send Message and Wait for Response, there are many discussions on this forum about using this functionality. It exists but its use is not encouraged.

Its use is not encouraged for Actor to Actor communications, because it locks one of the Actors until a response is received.  In the web service use case, the web service is supposed to block until a response is received. 

This is an intended use case for Send Message and Wait for Response.  This is why it exists.  Use it Use it if you go down the path of creating a temporary reply queue, passing a message and the reply queue to the Actor and waiting for a repsonse. 

IMHO, I think this makes more sense if you have a remote procedure call type of system where you're essentially returning the result of the command (otherwise you'd be needlessly polling for data and are open to race conditions).

If you have a data polling system where the web method is there just to expose some current values, then this approach may be too much infrastructure for the benefit, and something like a DVR could make sense.

Message was edited by: MattP

Cheers,

Matt Pollock
National Instruments
0 Kudos
Message 15 of 21
(1,589 Views)

OK, so I posted my other response before I saw this one, but you obviously understand that the AF portion of your application and the web services are indeed disconnected processes.  So, no matter what, you need to have a method for sharing information between the two processes. 

It seems to me that you are leaning heavily toward utilizing the controller actor queue.  In this case, you will need to maintain the queue in an FGV or some other type of global so that the web service can have access to the queue.  By explicitly sharing the queue reference with the web service, you have indicated that the service is essentially a portion of the controller (I am assuming that you will not be making the FGV available to the other portions of the application?  This would indeed break the intended use case of the AF). Now, ON TOP of creating this FGV, you will have to create a message that requests 1) the controller or one of its nested actors to do something and 2) create a response to that request.  This could be a simple request such as "give me your data".  But, you have already stored a reference to the actor in your web service, so why is it such a problem to just make a reference to the data in question available?  Using this method, you do not need to create a message to request the data and a message to return the data so now you have reduced the number of VIs you have created (2 classes with getters, setters and a 'Do' method) considerably AND you have not broken the AF paradigm.

Matt

0 Kudos
Message 16 of 21
(1,589 Views)

Matt,

You cannot wire a class object to the "Create DVR" Vi, all you get is a broken wire and an error message stating that "Polymorphic terminal cannot accept this data type". The only way to get it to work is to wire the individual data structures that the class owns to the "Create DVR" Vi. If you do this, you are breaking the encapsulation methodology of classes.

I believe that I agree with MattP that this is the intended use for Send Message and Wait for Response. The question is which method is going to produce less overhead, Send Message and Wait for Response or setting the Class up as a Global? There is considerable code on both sides, the Web Service and the Actor, that is going to need access to this information.

Later,

Eldon

0 Kudos
Message 17 of 21
(1,589 Views)

Eldon wrote:

Matt,

You cannot wire a class object to the "Create DVR" Vi, all you get is a broken wire and an error message stating that "Polymorphic terminal cannot accept this data type".

Eldon,

You have to change the properties for the class, it probably has the option to only allow members of the class to create a DVR of the class. That or create a method that belongs to the class and creates the DVR for you.

Regards,

Fab

For an opportunity to learn from experienced developers / entrepeneurs (Steve, Joerg, and Brian amongst them):
Check out DSH Pragmatic Software Development Workshop!

DQMH Lead Architect * DQMH Trusted Advisor * Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor

Have you been nice to future you?
Message 18 of 21
(1,589 Views)

Eldon,

It sounds like you may not be familiar with all the ins and outs of classes in LV.  The reason you can not just wire a class to a DVR has to do with the settings.  If you go to Properties -> Inheritance and look at the check boxes, you will notice the check boxes at the bottom.  By default, the box labeled "Restric references of this class type to member VIs of this class" is checked.  Uncheck this and viola!  You can now store the class in a DVR. 

dvr.png

Believe me, I do this regularly.  Most of my data structures themselves are classes.  And, as I said before, there are patterns and frameworks that rely on this functionality. 

But this is tangential.  You do not need to store the class in a DVR (although you could), you just want to store the DVR in the private data of the class.  You absolutely do not break the idea of encapsulation if you do this.  You can have a getter method that exposes the DVR that resides in the private data of the class if need be.

But regardless, you will need someway of sharing information amongst processes.  How exactly do you expect to get the queue reference (a member of your actor by the way) to your web service without bending your rules?  For interprocess communication, you have to have someway to get the information you need across.  And, you will be pushing that information (whether it be a queue reference or data owned by another class) outside of the bounds of the original class.

Obviously, you have to make a decision, but I would suggest that if all you need is data, then maintaining a reference to the queue and adding two classes to the system adds unnecessary complexity that only compounds your technical debt that you accumulate.

Let us know how you decide to go. 

Cheers, Matt

0 Kudos
Message 19 of 21
(1,589 Views)

Matt & Fab,

Thanks! I have done extensive OOP in C++ but when I started progamming in LV, the OOP was not very good. Now I am trying to pick it up again and need to learn how to use LV OOP, not the concepts.

Matt, you said:

But this is tangential.  You do not need to store the class in a DVR (although you could), you just want to store the DVR in the private data of the class.  You absolutely do not break the idea of encapsulation if you do this.  You can have a getter method that exposes the DVR that resides in the private data of the class if need be.

I think I understand what you are suggesting about storing the DVR as private data and exposing it but how about an example for clarifaction.

You also said:

But regardless, you will need someway of sharing information amongst processes.  How exactly do you expect to get the queue reference (a member of your actor by the way) to your web service without bending your rules?  For interprocess communication, you have to have someway to get the information you need across.  And, you will be pushing that information (whether it be a queue reference or data owned by another class) outside of the bounds of the original class.

I agree that you have to expose something in order to have communications between processes. The idea is to create the communications such that the caller is restricted by what the listener wants to expose. From your previous post, I see that you also understand this concept.

What I might be missing here maybe tied to the Web Service. The Web Service creates the root Actor and starts it thus getting access to the root Actor's message queue. This is good because on "Put" and "Post" URL calls you do not want the Web Service to become unresponsive waiting for the Actor to complete the task. What I need is to save the reference to the root Actors class. I guess it would be nice if the Web Service was more laid out to provide access scope to variables only needed by the Web Service.

Thanks,
Eldon

Message 20 of 21
(1,589 Views)