# Tag Change Scripts are not using current Script Module Edits after a Save Event

**URL:** <https://forum.inductiveautomation.com/t/tag-change-scripts-are-not-using-current-script-module-edits-after-a-save-event/59980>\
**Category:** Ignition\
**Tags:** scripting, ignition81\
**Created:** [May 24, 2022, 7:47pm UTC](https://forum.inductiveautomation.com/t/tag-change-scripts-are-not-using-current-script-module-edits-after-a-save-event/59980 "2022-05-24T19:47:02Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![dominicfabiilli](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dominicfabiilli](https://forum.inductiveautomation.com/u/dominicfabiilli)\
**Post date:** [May 24, 2022, 7:47pm UTC](https://forum.inductiveautomation.com/t/tag-change-scripts-are-not-using-current-script-module-edits-after-a-save-event/59980/1 "2022-05-24T19:47:02Z")

</div>

Ignition 8.1.14

I am working with a team on numerous projects that inherit scripts from the same global project.  
The Customer has decided to use Tag Change Scripts (not Gateway Events) to execute certain functions, and these are currently being called on Asynchronous threads.

My issue arises after I edit the global scripts, then I update and save the Global Project to publish the changes.  
Now, if I run my tag change script, it will end up using an older version of the script module (i.e. I am not seeing a logging message in my database that I had JUST added to the script call.)

Here is some further information that may help:

- We usually have anywhere from 1 to 15 designers open across our team on the same Gateway.
- The Development server we are using is integrated with GitHub for version tracking.
- My specific Tag Provider is not the default provider for the global project.
- Our “Gateway Scripting Project” is a layer BELOW the global project, so everything in global is accessible, but maybe not updating in the secondary project? (example: “GlobalProject” \> “SiteSpecificProject” \> [tag change event script calls])

Any thoughts? Thanks.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 24, 2022, 8:05pm UTC](https://forum.inductiveautomation.com/t/tag-change-scripts-are-not-using-current-script-module-edits-after-a-save-event/59980/2 "2022-05-24T20:05:52Z")

</div>

> [@dominicfabiilli](#):
>
> Asynchronous threads.

An asynchronous thread carries references to the complete interpreter in which they live. You must kill them off and start new ones when the code they are running (including anything called in other script modules) changes.

Not only is your failure to kill these off preventing them from calling your updated code, but they are leaking huge gobs of gateway heap memory.

(This is true of async threads no matter what kind of event starts them--gateway vs. tag is moot.)

Some guidance:

> [@Managing multiple asynchronous threads](https://forum.inductiveautomation.com/t/managing-multiple-asynchronous-threads/37185/2):
>
> To manage long-running jython threads through scripting restarts, you need to: Place the thread object in a dictionary that retains its content through script restarts. I used to recommend the dictionary from system.util.getGlobals(), but that is no longer suitable. I created a free [Life Cycle Module](http://forum.inductiveautomation.com/t/system-util-getglobals-not-persisted-across-designer-save/33869/14) that provides such dictionaries going forward. Write the asynchronous function’s loop so that it regularly checks [Thread.interrupted()](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html#interrupted--), particularly after any java I/O operations. Clean up …

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 24, 2022, 8:08pm UTC](https://forum.inductiveautomation.com/t/tag-change-scripts-are-not-using-current-script-module-edits-after-a-save-event/59980/3 "2022-05-24T20:08:00Z")

</div>

Also, don’t use `import` on any script module defined in an Ignition project. Use fully qualified names.

---

<div class="post-metadata">

**Author:** ![dominicfabiilli](https://avatars.discourse-cdn.com/v4/letter/d/c6cbf5/32.png) [@dominicfabiilli](https://forum.inductiveautomation.com/u/dominicfabiilli)\
**Post date:** [May 25, 2022, 1:20pm UTC](https://forum.inductiveautomation.com/t/tag-change-scripts-are-not-using-current-script-module-edits-after-a-save-event/59980/4 "2022-05-25T13:20:12Z")

</div>

So, would Gateway Events be safer or better performing than Tags? And in what way?  
I know I prefer using Gateway Events, and I have seen you post else where about this, but are there any specifics I should point out to the customer?

Also, Would you be able to suggest edits for my tag change script?  
This is what I have in a UDT Definition:

```auto
def valueChanged(...):

	import sys
	import traceback
		
	### This Function will be called on a new thread
	def delayExecution(params):
		packagesite.moduleexample.udtScriptCreateMESMaterial(params, currentValue, tagPath, missedEvents)
		
	### Actual Tag Change Event
	try:		
		params = {}
		if not initialChange and currentValue.quality.isGood() and bool(currentValue.value):
			oThread = system.util.invokeAsynchronous(delayExecution, [params])

	except:
		exType, exValue, exTraceback = sys.exc_info()
		packageglobal.exceptionhandling.exceptionLog(exType, exValue, exTraceback)

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [May 25, 2022, 2:30pm UTC](https://forum.inductiveautomation.com/t/tag-change-scripts-are-not-using-current-script-module-edits-after-a-save-event/59980/5 "2022-05-25T14:30:00Z")

</div>

> [@dominicfabiilli](#):
>
> So, would Gateway Events be safer or better performing than Tags? And in what way?

They are different. I prefer Gateway Events in a project over Tag Events in most cases. Factors to consider:

- Gateway Tag Change events have no queue limit--they don't lose events short of total gateway crashes. Tag Events are discarded when five pending events exist for the tag (by default).
- Gateway Tag Change events are singulated--all of the events for all of the tags listed are executed one event at a time. No parallelism eliminates some need for locking. But any slow execution can block action for other tags. By contrast, Tag events can run in parallel (three at a time by default).
- Gateway Tag Change events, as part of a project, are disabled if the project is disabled, and can use any script resources in that project. Their existence is independent of the tags they monitor. Tags in a monitor list are guaranteed to run the same code for the event. By contrast, Tag Events are part of the tag, can only use resources from the Global Scripting Project, and edits to individual tags can change the one tag's script. Deleting the tag deletes any trace of the tag's scripts, too.

If you need parallelism, then delegating to another thread is necessary for Gateway Tag Change events. Launching a dedicated thread is pretty heavyweight, though. I recommend creating a ThreadPoolExecutor and pushing your runnables to that. (See `later.py` for an example.)

Any such delegated event should still run straight through--no sleeps or infinite loops--to completion.

Your code launches a thread per event. Kinda' heavy, but not bad in and of itself. The question is whether the launched thread finishes (exits) quickly. The launched thread will not have access to updated script resources after it starts, and will hold its interpreter in memory until it exits.
