TagProvider.getTagConfigsAsync vs .browse

Hi all, long time no type.

TL;DR: Does ignition hold a lock while resolving tagProvider.getTagConfigsAsync("[$provider.name]", recursive=true, local=false) ?

I'm revisiting some code which we use in a plugin to analyze the entire gateway configuration tag space, running provider-by-provider.

We've seen experientially that while I'm running a scan of all tags, it seems to put a lot of load on the gateway of some sort, because the rest of the system runs into timeouts reading & writing to tags. I theorize that this is because the gateway is holding a sqlite table lock (or lots of row locks or or or) while doing these resolutions, so when we get to a vary large deep provider, it spends a long time recursively flattening the whole object, and that causes problems elsewhere.
The whole process takes about 180s to complete, so the performance gaps while this is happening are Not Great!

Standard metrics (thread pools I can monitor, cpu, ram, jvm gc etc) all seem fine.

Using that theory ("recursive=true holds a resource for too long, split the work up!"), I started exploring using the browseAsync api instead, but for my purposes I think that it's not suitable.
We use custom attributes on tags pretty heavily, and they don't come through the browse API at all. And I don't think that there's a path towards using getTagConfigsAsync without recursive=true because -- as far as I can tell -- there's no way to get tags under a path with it, just tags at a path.

Ignition 8.1.35 for API purposes, but this is important, if I need to upgrade I'll make it happen :smiley:

Any advice appreciated!

Not a lock exactly, but there is a single-threaded Executor that operations against a tag provider are executed on, including this one, and calling this with recursive=true at against the root of a large tag provider will block other operations until it completes.

Maybe you'll have to use some combination of browseAsync and getTagConfigsAsync?

1 Like

Thank you, that makes sense, I'll report back.

Thanks for your help @Kevin.Herron ! I can confirm that this works (switching back and forth between the browse api to discover children and the tagConfig API to fetch config at a point).

I see something unusual though.

Within the designer, when I use UDT I do see properties set on the template nested under the instance:

Screenshot 2024-09-18 at 13.00.22
(the instance of the UDT)
Screenshot 2024-09-18 at 13.02.24
(the definition of the UDT together with its template)

However, when I enumerate the properties of the same element with getTagConfigAsync(path/to/instance, recursive=true, localOnly=false) I don't see the inherited value show up, and I would have thought I would! Is there something I should be doing differently? The javadoc are pretty unclear about this unfortunately, so I appreciate your help!

The definition of the template from _types_ getTagConfigAsync is:

{
  "name": "Scannerish",
  "parameters": {
    "prefix": {
      "dataType": "String"
    }
  },
  "tagType": "UdtType",
  "tags": [
    {
      "sourceTagPath": {
        "bindType": "parameter",
        "binding": "{prefix}/{InstanceName}"
      },
      "valueSource": "reference",
      "dataType": "String",
      "name": "data",
      "AutoSub": true,
      "tagType": "AtomicTag"
    },
    {
      "AutoMqtt": {
        "bindType": "parameter",
        "binding": "none:fakeMqtt/{InstanceName}"
      },
      "valueSource": "memory",
      "AutoSrwx": 7,
      "name": "dirproxy",
      "tagType": "AtomicTag"
    }
  ]
}

(pay attention to those AutoSub and AutoMqtt, that's what I want to see again in the future...)

while the getTagConfigurationAsync(path, recursive=true, localOnly=false /* or true, doesn't matter*/) is:

{
  "name": "event1",
  "typeId": "Scannerish",
  "parameters": {
    "prefix": {
      "dataType": "String",
      "value": "Realish"
    }
  },
  "tagType": "UdtInstance",
  "tags": [
    {
      "name": "data",
      "tagType": "AtomicTag"
    },
    {
      "name": "dirproxy",
      "tagType": "AtomicTag"
    }
  ]
}

My suspicion is that I don't understand localPropsOnly, because if I pick a tag I expect to inherit a property from the template and attempt to getTagConfigAsync that tag's path (like: dirproxy & expect to see AutoMqtt in the above example), I still don't see the expanded property set I expect in the result.

I'm attempting to probe for the custom properties on the returned model with TagConfigModel.get(myPropertyName), and falling back to this json print for debugging.
I think the get is failing to find the value -- but I am not sure, which is why I am debugging.
But it might be and my bug is somewhere else, or maybe I'm misunderstanding something and should be evaluating these differently somehow?
Maybe I should use different tag paths when expanding UDTs? Or a different definition of the properties (they're BasicPropertys) or something?

anyway, please let me know and thank you!

Update:
The parameters I want are present in the TagConfigModel.inheritedConfiguration (and afaict more reusably, they're also flattened into the TagConfigModel.values so I don't even have to check local inherited separately, which is nice)!
However, I'm not done yet.

In my example both versions used bindings. And the expressions that use bindings seem to be returned raw (which is useful, but not perfect).

Is there an API to get the evaluated version back? I begin to suspect (per Tag Paths | Ignition User Manual ) that I should explore with the browse API, fetch property sets with the tagModel API to see if the fields I want are present, and then evaluate the actual properties with the read API (using the same path as the parent but with a .someProperty at the end). Yeah?

(actually, looks like the tagModel API is pretty optional if I'm going to end up looking for the values I know I want anyway with read(some/path.someProperty) since I know which properties I care about)

Utter success!

So: for my purposes, the TagModel api is good but not great; async reads to the properties I knew I wanted anyway were a lot more straightforward. Thanks for your help; happy to suggest or donate docs if that would be useful!