Get a flat list of all tags paths on the gateway?

Recursive browsing to get a list of all the tags is really slow because for each new folder/level the client has to send a new request to the server. I have had my recursive tag browse method tag actual minutes to complete.

Is there any way to get a flat list of tag paths from the gateway?

Here is my Browse method for reference

def browseTags(path, filt):
	try:
		results = system.tag.browse(path, filt)
		returnResult = []
		for result in results.getResults():
			# If the item has children, call the function to repeat the process but starting at the child.
			if result['hasChildren'] == True:
				try:
					returnResult.extend(browseTags(result['fullPath'], filt))
				except:
					print("Failed on Path: " + result['fullPath'])
			else:
				print("Tag Found: "+ str(result))
				returnResult.append(result)		
	except:
			print("Failed on Path: " + path)
			print("Result: " + str(results))	
	return returnResult

As of 8.1.2 you can pass a recursive: True parameter in your system.tag.browse call to have the recursion happen on the gateway automatically.
https://docs.inductiveautomation.com/display/DOC81/system.tag.browse

1 Like

Don’t do it! It’ll eventually grow to take longer than the client comms timeout. Use message handlers in both directions. Cache results in a project script on the gateway (and client, too, maybe).

2 Likes

Phill, could you elaborate a bit on this method?

First, any recursive operation on the tag hierarchy should be executed on the gateway, not from a Vision client. The answer is not likely to be returned within the gateway message timeout for anything but the simplest tag hierarchy.

When a gateway API can reasonably be expected to every take more than 60 seconds, and you can't refactor your use case to avoid it (after really trying to avoid it), you can use a pair of message handlers to get around the problem:

  • Call a gateway message handler using system.util.sendRequest(), supplying the details needed for the long-duration API call, and the client's own ID. The message handler creates a unique ID code for the request, hands it all off to an asynchronous thread, and returns the ID code to the client.

  • The calling client places that ID code and a callback function into a project script top-level dictionary.

  • The gateway thread, upon completion, assembles the real response and ID code into a payload, and uses system.util.sendMessage to deliver to the original requesting client.

  • The client message handler that receives the response "pops" the ID code out of the local script module's dictionary, and calls the callback function with the response.

  • The callback function does the rest of the logic that would have been after the unmitigated API call.

2 Likes

Phil is 100% correct. That recursive function works great in a test system with a few dozen tags, but it doesn't work at all in a production environment with thousands of nested tags. It takes way too long to run its course.