DQMH Consortium Toolkits Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

What is a good method that is used specifically for notifying other modules when any given module has started/restarted?

Solved!
Go to solution

Ok, I know. Too many of my own posts.  I go away for two days and then come back and my brain is on overload trying to figure this out.

 

After re-reading the linked article yet again, I had an insight.  I may have significantly misinterpreted or misconstrued what Sam was saying in his article.  I relation to his tree diagram, think I have it in my head that a module is typically it's own root actor.  Some modules have nested actors (modules that control other modules).  And because most modules are the root actors, there are multiple root actors within a single application (i.e., the DAQ would be a root actor and the Data Logger would be a root actor).  What I don't understand then is how all of the root actors communicate within an application.

 

Or I need a better understanding of Sam's tree structure of an actor model in general.  Again, I have never done actors, plug-ins, etc prior to this project.  Is the root actor always the top level?

 

Ok, hopefully one of those ideas relates to someone and you can provide the answer that I am seeking.  (And hopefully I can understand your answer.  Because it is possible that the answer is above and I am not bright enough to understand the answer without it being spelled out.)

 

Thanks again,

 

Scott

 

0 Kudos
Message 11 of 16
(3,620 Views)
Solution
Accepted by doyles

Hi Scott,

 

Let me use a real application we have worked on. The application has more than 20 DQMH modules, so I won't describe everything, just the key points for the problem at hand.

 

The top level module is in charge of launching the main modules, these are the modules the top level is interested in for error logging, status updates and user permission management. The modules themselves might launch other modules, as long as the launcher is the only one that wants to listen to broadcasts. If there happens to be a broadcast a higher module needs, then you need to decide if the launcher relays back the broadcast via a broadcast of their own (tree model) or if that module belongs at the top level or if the top level assumes when the launching module broadcasts "did init" that the top level will registers for the lowest modules broadcast as well (least preferred method). Actor Framework opts for encouraging tree calls for all cases. DQMH leaves this decision to the architect.

 

Next key item is the "avoid circular dependencies" practice. The highest level module only sends requests to the modules it launches and registers for broadcasts for any module. Requests are named using imperative form and Broadcasts are named using past tense.

 

On our application, the top level launches a Database Table UI module that is the main user interface for the end user. The top level also launches a Third Party program controller. It is a smaller window. The Database Table UI module starts sessions that communicate with that Third Party program DQMH. The Database module doesn't launch the Third Party DQMH.

 

The database module sends a request to the Third Party program to "start session" and reacts to its broadcasts.

 

Now, if the Third Party program stops responding (we are dealing with a black box here not written in LabVIEW, it is not the most stable exe out there). The end user might not have access to the Third Party DQMH window. The end user uses a utilities button on the Database Table UI module to broadcast "needed to restart Third Party". Notice that we use past tense and a broadcast. The database module is saying "I have no control over starting this module, somebody out there has that control and hopefully is listening to my broadcasts". 

The highest level module is registered for this broadcast and relaunches the Third Party DQMH, it also sends a request to all the modules it knows depend on this Third Party DQMH to register again for the Third Party DQMH broadcasts.

When the Database Table UI receives the request to register again for Third Party DQMH module events, it registers for them again and communication resumes with the Third Party DQMH.

 

I hope this helps,

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 12 of 16
(3,607 Views)

@doyles wrote:

And because most modules are the root actors, there are multiple root actors within a single application (i.e., the DAQ would be a root actor and the Data Logger would be a root actor).  What I don't understand then is how all of the root actors communicate within an application.


I guess there's some place in your code that starts both the DAQ and the Datalogger module, right? So I would argue that, no matter if that piece of code is a DQMH module, an actor, or anything else, it's the root node of your module architecture. This root node is in charge of handling all branches it grows (=modules it starts).

dqmh-tree.001.jpeg

 

Take the application in the picture. A VI called main.vi launches the DAQ and Datalogger modules. DAQ launches a NI-DAQmx module itself, and Datalogger launches a Database module.

 

When launching the modules, main.vi could launch DAQ first, get its broadcast references, then launch Datalogger and hand the DAQ broadcast references to Datalogger (as a request, not as parameter for Start Module.vi).

 

If now DAQ stops or is stopped, the broadcast references in Datalogger go stale. As main.vi is the one place in your application that's in charge, somebody would tell main.vi to restart DAQ. Now the same thing would happen that had happened before: main.vi launches DAQ, get its broadcast references, and hands them to Datalogger again (possible because we made this a request and not a startup parameter).




DSH Pragmatic Software Development Workshops (Fab, Steve, Brian and me)
Release Automation Tools for LabVIEW (CI/CD integration with LabVIEW)
HSE Discord Server (Discuss our free and commercial tools and services)
DQMH® (Developer Experience that makes you smile )


Message 13 of 16
(3,585 Views)

Hi Fab,

 

Thanks for the response.  This definitely helps.

 


wrote:

Next key item is the "avoid circular dependencies" practice.  


This is exactly what I felt like I was on the verge of doing.  I started this thread to make sure I was avoiding this, or something similar.

 


The database module is saying "I have no control over starting this module, somebody out there has that control and hopefully is listening to my broadcasts". 


This is exactly the scenario that caused me to pause before I changed the code to operate in this manner.  Configuring the communications like this made me feel like I might be heading down a slippery slope.  Are there any big "gotchas" with this communication method? 

 

Either way, thank you for giving me the confidence to make the changes that would result in this being how certain modules operate.

 


Now, if the Third Party program stops responding (we are dealing with a black box here not written in LabVIEW, it is not the most stable exe out there). The end user might not have access to the Third Party DQMH window. The end user uses a utilities button on the Database Table UI module to broadcast "needed to restart Third Party". Notice that we use past tense and a broadcast.with the Third Party DQMH.


Thanks for highlighting the past tense naming tip as well.  This might be one of those small details that helps the whole picture make sense and not get confusing.

 

Thanks again,

 

Scott

Message 14 of 16
(3,566 Views)

Hi Joerg,

 


@joerg.hampel wrote:

I guess there's some place in your code that starts both the DAQ and the Datalogger module, right? So I would argue that, no matter if that piece of code is a DQMH module, an actor, or anything else, it's the root node of your module architecture. This root node is in charge of handling all branches it grows (=modules it starts). 


Does root node = application top-level?  No if's, and's, or but's?  That is what I am getting from your diagram and from what you're saying.

 

Or does it - at least could it - mean simply the controller of those modules.  It would indeed handle all of the modules it starts/branches it grows.  I ask because if it is simply the controller of those modules, something else could start/control that controller.  I keep thinking that it makes sense to call those reusable modules from the same place for every application.  So a "root node of the reusable modules" versus the "root of all roots".

 

Based on Fab's reply above, and yours here, I still think that the method I proposed in Message 6 on this thread, where Module D controls the DAQ and Dataloger modules, fits within all of your suggestions (at least as long as root node of those modules does not have to equal the application top level).

 

In this scenario, Module D would be called by the top-level of the application and interface only with the top-level and the modules that is starts/grows.  Module D would pass the started module references to the top-level, which would relay those to any other interested modules.  If the the DAQ (logger, etc) stops for any reason, then those other modules could/would send the "Needed DAQ to Restart" message to the top-level, which would relay that broadcast to Module D.  Then Module D would restart the DAQ and resend the references to the top level using the same method as when it initially started.

 

That seems to be almost exactly what you're stating, with one other level above the root node.  Since that doesn't sound like a root node as shown in the image, I am asking for clarification.

 

Side note: It seems like as the code approaches the top level (of the tree) it is then referred to as the root.  ????

 

 


When launching the modules, main.vi could launch DAQ first, get its broadcast references, then launch Datalogger and hand the DAQ broadcast references to Datalogger (as a request, not as parameter for Start Module.vi).


Thanks for this noting that distinction as well.

 

Thanks again Joerg.  I really appreciate you and Fab walking me through these pain points. 

 

Scott

0 Kudos
Message 15 of 16
(3,563 Views)
Solution
Accepted by doyles

@doyles wrote:

That seems to be almost exactly what you're stating, with one other level above the root node.  Since that doesn't sound like a root node as shown in the image, I am asking for clarification.

 

Side note: It seems like as the code approaches the top level (of the tree) it is then referred to as the root. 


Yes, exactly. This tree that we talk about can have any number of nodes / levels. And the idea of reuse is that you can pick a subset and use it somewhere else. I'm far from being an OOP/Tree expert, but that's how I see it. Having said that, I'm not sure I would create a "Reusable Code Manager" module, but that's just me with my very limited knowledge of your application and architecture.

 

Also, as to the term root, I was just trying to describe the uppermost node of the tree. I don't know of any global and/or generic definition of this term, so it was just an arbitrary choice of words. Now that I think of it, root is the wrong description of the picture we're drawing here, it would have to be treetop or top, right? And taking this thought experiment even further, maybe I should be talking about a bush that branches from the bottom...

 

This also goes to show nicely that there's a lot less right/wrong than we think sometimes (at least that's what I keep telling myself).

dqmh-tree.001.jpeg




DSH Pragmatic Software Development Workshops (Fab, Steve, Brian and me)
Release Automation Tools for LabVIEW (CI/CD integration with LabVIEW)
HSE Discord Server (Discuss our free and commercial tools and services)
DQMH® (Developer Experience that makes you smile )


Message 16 of 16
(3,548 Views)