Gateway Tag Change Scripts and Timer

I have memory tags which I want to attach scripts to run when the value is changed. I am using gateway tag change since these are able to access scripts from my project library. I want to run a script on value change and it should check a progress tag and if that tag is true, it should hold the script on another thread until the progress tag is false so that other scripts can continue to run.

from threading import Timer

currentValue = event.getCurrentValue().value
in_progress = system.tag.readBlocking('[~]IN_PROGRESS')[0].value
t = None

if currentValue:
	
	def foo():	
		global in_progress,t
		system.util.getLogger('x').info('hit')  #log file does not show 'hit'
		in_progress = system.tag.readBlocking('[~]IN_PROGRESS')[0].value
		if in_progress:
			t = Timer(1,foo).start()
		else:
			... do something

	Timer(1,foo).start() #foo is not executing 

This seems to not work on gateway scripts because doing a test on perspective views will work.
Does gateway not support this? I am thinking of using time.sleep() since it does seem to work but from past experience time.sleep() is not ideal to use.

What about the tags requires the scripts to be run sequentially as opposed to on change? In other words, what is the IN_PROGRESS tag tracking? Are you trying to manage state?

Gateway Tag Change Scripts run in independent threads, so there is no need to "pause" running a particular tags change event while another is working.

My tags (lets say a,b,c,d,e,f,g), some tags will have an db operation which will trigger IN_PROGRESS to be active. When one of the a-g tags values changes to True, its script gets executed but if the IN_PROGRESS is active, it will wait till it is not active before continuing to run. I can't have the tags running sequentially because there is thousands of tags and I need the tags to run only on value change to True.
But, if what you are saying that these scripts run on independent threads I should be fine using time.sleep() since I was worried that it would 'freeze' up other scripts running on the same thread.

I am still not understanding what you're trying to accomplish. Can you answer these questions:

  1. Are your tags a-g related to each other?
  2. Can the scripts on those tags not run independently of the others?
  3. What tag value changing to True is the trigger? Is it each tag?
  4. Why do you need IN_PROGRESS?

Your OP suggests the opposite of this, why else would you pause the execution of a script until another script completed unless your intention was to have it run in a specific sequential order?

1 Like
  1. No
  2. They need to run independently
  3. a-g tags all are boolean which triggers when value changing to True
  4. Some tags will perform a database operation and while it is performing this operation, other tags need to wait till it is done.

So,
12:00 pm - A tag changes and script starts to run and does db operation and IN_PROGRESS changes to True.
12:01 pm - B tag script changes and script starts to run but it also does db operation so it has to sit there until A finishes before it can complete.
12:01 pm - C tag script changes the same time B tag script changes but this tag does not do db operation so it can run and complete without waiting.
12:03 pm - D tag script changes, this performs db operation so it has to wait till A and B tag scripts finishes.
12:04 pm - A finishes, IN_PROGRESS changes to False, B tag script can now do its thing.

When I did my OP, I was under impression that scripts would have to run on same thread, which will cause other scripts to 'freeze' when I use time.sleep(), which was why I wanted to make my scripts run on another thread. But, when you said scripts would run in independent threads it sort of cleared things up.
I hope I was a bit more clear here...

I think you are over complicating things.

The tag change events do run in separate threads, however, DB operations are blocking (they wait until a return). This means that the thread will automatically halt until its data is returned from the DB.

You should let the DB manage any locks that need to occur because the same table is trying to be updated by multiple queries.

Your sequence should really just be the following:

12:00 pm - A tag changes and script starts to run and does db operation. This call reaches the DB where the DB engine handles any needed locks on tables due to inserts or updates. DB operation is processed, values are returned and script completes.
12:01 pm - B Tag script changes and script starts to run. This call reaches the DB where if the table is locked the DB waits for some defined timeout. Once available DB operation is processed, values are returned and script completes.
12:01 pm - C Tag script changes and script is run and completes.
12:03 pm - D tag script changes, this call reaches the DB where if the table is locked the DB waits for some defined timeout. Once available the DB operations is processed, values are returned and script completes.

There is no need to force the scripts to wait, that will be handled for you by the DB engine.

For point of reference, my MSSQL connection is currently fielding 16 queries/sec.

1 Like

Do you know ahead of time which tags need to do DB operations?

If so, list them all on a single Gateway Tag Change Event and they will run one at a time. List all the quick tags on one or more other Gateway Tag Change Events. (Each definition with list gets one thread.)

If not, then Ignition doesn't have a native event type that does what you want, and any form of .sleep() of jython Timer is a big no-no. A hybrid approach that uses a persistent queue of database operations, filled by a fast tag change event, and drained by a fast timer event (dedicated thread for that latter) may be needed.

Share more details.