to subscribe to expressions using connect(CommonContext var1, InteractionListener var2)
I have a callback method I provide for var2 that is working fine, its triggering when I update the tag value that is in the expression.
I am testing it out with a redundant system and for some reason when I failover to the backup gateway the callback is not being invoked. My code uses the com.inductiveautomation.ignition.gateway.redundancy.RedundancyManager to listen for the change in redundancy and when the backup gateway becomes active I make sure to connect to the expressions but still the callback is not being invoked. When the primary gateway becomes active again it works just fine.
Why would it not work on the backup gateway when it is active? Is there a certain way or event I need to wait for before connecting the expressions on the backup?
I suspect you have mistaken that method's purpose. It is called by binding infrastructure in the platform when an expression instance starts up. The interaction listener is not expected to be used by "pure" expressions, as its purpose is to cause infrastructure to re-execute the expression, when something internal to the expression changes.
There are many possible ways for you to screw this up if you are pretending to be infrastructure yourself. But if you are not pretending to be binding infra, you're certainly screwing up.
not sure what you mean by “pure” expressions. My need is to subscribe to ignition expressions so that when they change I can re-execute the expression in my module and use that new value to trigger some behaviour.
Does this sound like something this library is not intended for? is there any other library that i can use to watch expressions for changes in their values?
Maybe some more context would be helpful? I have a perspective form that lets users save entities into our database and one of the fields in this entity is an expression field that will trigger some logging when the value goes true, and then stop when the value goes false. When they hit save, I am calling a method in my module to store the expression and to subscribe to it with a provided callback on change. Internally when that callback is invoked it publishes an event that can be listened for by other parts of my module that manage the logging behaviour. This has been working perfectly up until I started testing out what happens when the backup gateway takes over; we get silence, no callback invoked, no event.
I'm shocked that works. (What happens when the user closes or changes view? I suspect you are leaking memory by holding a reference to the expression.)
Is this expression fixed? If so, you should be implementing it directly in java with tag subscriptions, and performing the logging there. Your form should not have it, but should only tell your module what tags to add to the monitoring (or remove).
the expression is saved in my database. The view doesn’t hold the data. The form is just to input the data, all the rest is just done in the module.
Once the form submits the expression is held in memory in the module yes but it is bound by the lifecycle of the module and bound by a subscription id in a hashmap.
There is a global expression state im holding in memory (its not large and constrained by lifecycle and unique id). The submission in the form calls my a scriptable method in my module to add an expression to the subscriptions.
Ok. You are running your own expression infra completely separate from the UI? I would expect it to work the same on both master and backup. But you may need to call connect() when failing over, and disconnect on the inactive gateway.
My code uses the com.inductiveautomation.ignition.gateway.redundancy.RedundancyManager to listen for the change in redundancy and when the backup gateway becomes active I make sure to connect to the expressions but still the callback is not being invoked. When the primary gateway becomes active again it works just fine.
My question being; is there any reason why it may behave differently on the backup? are the callbacks being suppressed on the non-primary gateway even when it becomes the active one? I can understand wanting to suppress this stuff on non-primary gateways while it is not active to avoid duplicate and unnecessary behaviour but its looking like its not working even after becoming active. I am using com.inductiveautomation.ignition.gateway.redundancy.RedundancyManager.addRedundancyStateListener() to capture any state change in redundancy and on whatever node is active queries my database for the expressions and connects to them all again (regardless of role). I confirmed using logs and debugger that both nodes when active have the right set of expressions and have connected to them but the callback just isnt happening when the backup is the active node.
This is, frankly, a pretty bizarre use case that I can't imagine anyone envisioned, so I'm not totally surprised it doesn't work. I still don't really understand what you're doing.
What, exactly, does using our expression mechanism get you at all? Could you just...have your own set of interfaces/classes/etc that you manage entirely on your own?
It lets users control the logging behaviour of my module through tags. Really it lets me use tags to trigger events inside my module that could be used for any number of things (logging, database interactions, api calls, anything I want)
Are tags really the 'right' place for that kind of thing? It just seems convoluted - the general practice in Ignition would be to expose that kind of thing as scripting functions.
Not trying to convince you to rewrite everything you've got, necessarily, but if you weren't aware, the SDK is provided entirely on a "best effort" basis of support - if there's a bug here (which I'm not convinced of) it's not anywhere near top priority to fix, so if your priority is getting user experience the way you want, it might be better to hew closer to what we do first party.
No, the supported techniques are various ways to subscribe directly to tags. The expression subsystem is exposed for module authors to supply new functions. Your usage is not intended, and you are on your own. (Not that it isn't interesting.)
connect is intended to be called from anything that is setting up expressions to run. So it's called from a variety of places throughout the codebase, as part of their scaffolding before running the expression. It's not intended to be called from a module that is only providing expression functions.
Sure, IA can do what they want. Nowhere do they show or even suggest that you would create and execute expressions yourself via the SDK. But nowhere do they forbid it. It just isn't something IA is supporting.
If you figure this out yourself, more power to you. (And I hope you share.)