The AF Msg Forwarding Utility Revisited

Looking Back

When we first introduced the Zyah AF Msg Forwarding Utility in 2021, the intent was to make it easier to send AF Msgs from one part of the tree to another without the need to duplicate (or at least create very similar) Msgs at each node in the tree. A key part of accomplishing this was using interface inheritance to automatically determine which actors in the application could implement specific Msgs. Receiving actors that didn’t inherit from the Msg interface forwarded the message upward. Actors that did inherit from the interface forwarded the message downward.

This method has served us well and there are two areas where we’ve found where the Forwarding Utility provides enormous benefit:

  • Nested GUIs - Complex GUIs are often broken down into smaller encapsulated components. These components themselves may be further divided into smaller sub-components. With nested GUI architectures like this, sharing data to display across components is tedious using traditional actor messaging. Similarly, if a deeply nested GUI captures a user action, communicating that action up the tree to the appropriate actor can be equally aggravating. The Forwarding Utility elegantly resolves these problems.

  • Plugin Architectures - Our clients often want the ability to extend existing applications to support new test and control instruments. In fast-paced development, rebuilding applications every time there’s new test hardware can be unwieldy and time-consuming. Zyah’s use of plugin architectures allows the support of new plugins and functionality without the need to rebuild the core application. With traditional static actor messaging, supporting plugins while retaining the benefits of strictly-typed Msgs is challenging and usually requires compromising with type casting and case structure checks. The Forwarding Utility allows dynamic plugin support while still providing the safety of strict typing.

Still not perfect

While the Zyah AF Msg Forwarding Utility’s use of interface inheritance helped make our architectures both simpler and more adaptable, we did encounter some caveats that we would need to work around:

  • Inheritance discouraged reuse - Inheritance can only be defined statically during edit time, so it becomes difficult to reuse generic Msg proxy actors. For example, let’s again consider the nested GUI use case. Suppose your primary GUI actor is comprised of multiple nested GUI actors. It might make sense to reuse the primary GUI in different applications, while embedding different nested GUI actors tailored to each application. However, in order to forward Msgs “down” the Msg tree to the subpanel actors, the primary GUI would need to inherit from the appropriate forwarding interfaces. Different applications use different interfaces and the inheritance needs to change. Because the primary GUI actor’s inheritance is defined statically, it can’t be directly reused between applications.

  • Bi-directional forwarding not allowed - Suppose you have an instrument manager actor that launches a DMM actor. The DMM actor acquires data and sends it (via forwarding) back to the instrument manager. Now imagine the instrument manager wants to forward that information up to the application root actor (where it then goes to some sort of data logging actor) AND to a debug GUI that could be launched by the instrument manager. With forwarding via inheritance, this isn’t possible because only one forwarding direction is allowed. You would need to manually “forward” the Msgs to the debug GUI or the data logger instead.

  • “Must Override” requirements need to be disabled - Because each node in the tree needs to inherit from an interface in order to forward Msgs to its nested actors, those nodes often do not have their own override of the payload method associated with each Msg. By default, interface methods must be overridden by any class that inherits from them, but in this case, that requirement had to be disabled which removes edit-time errors due to lack of implementation in the actor that actually consumes the Msg. While this isn’t catastrophic, it’s not ideal either.

So although the Zyah AF Forwarding Utility provided substantial benefit, there were also areas for improvement. After implementing multiple applications using the original version, we are releasing a new version of the Forwarding Utility which addresses the above pain points while also improving on the existing functionality.

What’s old is new again…

We’ve rewritten the Zyah AF Forwarding Utility (v3) from the ground up and changed from determining forwarding by inheritance to forwarding by registration. To enable Msg forwarding, Actors simply register themselves as either sources or sinks of Msg interfaces. This ends up looking a lot like a publish/subscribe paradigm, but a key difference is that there is no centralized message broker. Everything is handled under-the-hood while still adhering to best actor messaging practices (i.e. no shortcutting of the actor Msg tree).

NOTE: Version 3 of the Forwarding Utility is a major breaking change from version 2.x and earlier. If you rely on the older version, do NOT upgrade until you’re ready to incorporate the new API.

By relying on dynamic registration defined at run-time instead of static inheritance defined at edit-time, the new Forwarding Utility possesses several advantages:

  • Actor reuse is easier - Proxy actors don’t need to know anything about what their nested actors can or cannot support in order for Msg forwarding to work. Relationships are dynamically established at run-time.

  • Bi-directional forwarding is possible - An actor can forward messages that come from one nested actor both up to its caller AND down to other nested actors. (We do some clever tricks to prevent infinite Msg loops between two actors.) Going back to the example above, you can now have a debug GUI and a data logger both receive forwarded data no matter where in the actor tree they are.

  • “Must Override” requirements work by default - The default requirement to override methods of an interface in a class that inherits from said interface have been restored. This allows for better edit-time error detection.

  • Debug APIs - Since forwarding relationships are defined dynamically, it makes sense to provide APIs to peak into what they are for a particular actor. We provide such an API in this version of the utility.

  • Simplified APIs - Previously, in order to maintain the list of interfaces to forward consistent within an application you either had to use inheritance or make a copy of the forwarding utility and pass it to each nested actor. Dynamic registration does away with this making it easier for developers to quickly integrate and deploy in their existing applications.

Important Notes

The new forwarding utility differs in key ways from the original utility, which requires some adjustments in terms of design considerations.

  • Msg sources AND sinks both need to register explicitly to enable forwarding. However, nodes in the middle of the journey don’t need to do anything. Explicit registration on the block diagram is arguably more readable (as opposed to relying on inheritance defined via class properties).

  • In order to incorporate the ability to forward Msgs into every actor in your application, it’s easiest to have a common Base Actor define this functionality. There’s a Forwarding Base Actor included with the utility that you can inherit directly. Alternatively, if you don’t want to change your existing class hierarchy (e.g., if you use the MGI Monitored Actor) you can copy the functions into your existing base actor. The simplified API makes this pretty easy to do. (Of course, feel free to reach out if you have issues and we’d be happy to help.)

 

Where to Get It

There are two options available to get the forwarding utility:

  1. VIPM
    This is available as a package on VI Package Manager.
    https://www.vipm.io/package/zyah_solutions_lib_zyah_af_msg_forwarding/

  2. GitLab
    You can also do a direct pull of the source code from GitLab. We just ask that if you make any improvements, you share it with the community.
    https://gitlab.com/zyah-solutions/community-tools/zyah-af-msg-forwarding-utility

If you have any questions or feedback, feel free to reach out to us by e-mail or by joining us on our Discord.

Next
Next

The Zyah Auto Update Utility