# Persistent Storage of Global Context

**URL:** <https://discourse.nodered.org/t/persistent-storage-of-global-context/15104>\
**Category:** General\
**Created:** [4 September 2019 13:20 UTC](https://discourse.nodered.org/t/persistent-storage-of-global-context/15104 "2019-09-04T13:20:41Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![rholmesa](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rholmesa/32/29252_2.png) [@rholmesa](https://discourse.nodered.org/u/rholmesa)\
**Post date:** [4 September 2019 13:20 UTC](https://discourse.nodered.org/t/persistent-storage-of-global-context/15104/1 "2019-09-04T13:20:41Z")

</div>

Hi,  
Windows 10 - NR 0.20.7  
I have been trying to use persistent storage to allow continuation over a restart. I have set the contextStorage to 'localfilesystem'. I can see the files as described in the documentation so I assumed all was well until I lost some global context items as follows:

I defined an object to be stored in global context (global.set("xxxx")) which consists of a set of methods and a data array associated storing the status of various devices. The methods allow access to the array, greatly simplifying and standardising updates etc.

```auto
stats1 = {
	getname : function() {
	    var addr = arguments[0];
		var name = "Not Known";
		for (var devnum in this.devices) {
			if (addr == this.devices[devnum].address) {
				name = this.devices[devnum].name;
			}
		}
		return name;
	},
	setname : function() {
	    var addr = arguments[0];
		var name = arguments[1];
		for (var devnum in this.devices) {
			if (addr == this.devices[devnum].address) {
				this.devices[devnum].name = name;
				return devnum;
			}
		}
		return -1;
	},
	getaddr : function() {
	    var name = arguments[0];
		var addr = "Not Known";
		for (var devnum in this.devices) {
			if (name == this.devices[devnum].name) {
				addr = this.devices[devnum].address;
			}
		}
		return addr;
	},
	setaddr : function() {
	    var name = arguments[0];
		var addr = "Not Known";
		for (var devnum in this.devices) {
			if (name == this.devices[devnum].name) {
				this.devices[devnum].address = addr;
			}
		}
		return addr;
	},
	setvisible : function() {
	    var addr = arguments[0];
		var what = arguments[1];
		for (var devnum in this.devices) {
			if (addr == this.devices[devnum].address) {
				this.devices[devnum].visible = what;
			}
		}
		return addr;
	},
	add : function() {
	    var addr = arguments[0];
	    var dev = {};
	    var date = new Date();
        dev.address = addr;
        dev.name = "Device" + (this.devices.length);
        dev.value = "Not Set";
        dev.date = this.formatDate(date);
        dev.time = this.formatTime(date);
        dev.visible = false;
		this.devices.push(dev); // add to array
		return this.devices.length;
	},
	exists : function() {
	    var addr = arguments[0];
		for (var devnum in this.devices) {
			if (addr.toUpperCase() === this.devices[devnum].address.toUpperCase()) {
				return devnum;
			}
		}
		return -1;
	},
	updateValue : function() {
	    var date = new Date();
	    var addr = arguments[0];
		var what = arguments[1];
		var exists = this.exists(addr);
		if (exists !== -1) {
			if (what.toLowerCase() !== "silent") this.devices[exists].value = what;
            this.devices[exists].date = this.formatDate(date);
            this.devices[exists].time = this.formatTime(date);
		}
		return exists;
	},
    formatDate : function(date) {
        var d = date,
            month = '' + (d.getMonth() + 1),
            day = '' + d.getDate(),
            year = d.getFullYear();
    
        if (month.length < 2) month = '0' + month;
        if (day.length < 2) day = '0' + day;
    
        return [day, month, year].join('/');
    },
    formatTime : function (date) {
        hours = '' + date.getHours();
        if (hours.length < 2) hours = "0" + hours;
        minutes = '' + date.getMinutes();
        if (minutes.length < 2) minutes = "0" + minutes;
        seconds = '' + date.getSeconds();
        if (seconds.length < 2) seconds = "0" + seconds;
        return [hours, minutes, seconds].join(':'); 
    },
	devices : []
};

```

Anything stored within the 'devices' array is persisted, the methods are not!

Am I breaking some rules I don't know about or should this work?

Regards

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [4 September 2019 13:31 UTC](https://discourse.nodered.org/t/persistent-storage-of-global-context/15104/2 "2019-09-04T13:31:40Z")

</div>

Context can only persist JSON encodable data. You cannot persist javascript code.

---

<div class="post-metadata">

**Author:** ![rholmesa](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rholmesa/32/29252_2.png) [@rholmesa](https://discourse.nodered.org/u/rholmesa)\
**Post date:** [4 September 2019 13:33 UTC](https://discourse.nodered.org/t/persistent-storage-of-global-context/15104/3 "2019-09-04T13:33:03Z")

</div>

Thanks for the prompt reply.

I'll think of something else.

Rgds

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [4 September 2019 21:41 UTC](https://discourse.nodered.org/t/persistent-storage-of-global-context/15104/4 "2019-09-04T21:41:00Z")

</div>

You might want to think about this the other way around. Assuming you want those functions to be available to multiple function nodes, you can define them in settings.js (in the globals section) and then reference them in your function nodes.

To make things more sustainable and manageable, you can also move the function definitions to your own module and then use `require` statements in settings.js.

---

<div class="post-metadata">

**Author:** ![rholmesa](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rholmesa/32/29252_2.png) [@rholmesa](https://discourse.nodered.org/u/rholmesa)\
**Post date:** [5 September 2019 00:19 UTC](https://discourse.nodered.org/t/persistent-storage-of-global-context/15104/5 "2019-09-05T00:19:26Z")

</div>

Thanks @TotallyInformation.

I have never considered that. It’s been useful in development to be able to modify the functions ‘on the fly’ and just save them in the one object. Re-deploying and re-saving then makes them available immediately without the need to restart.

As a current workaround, at restart Check for the existence of one of the functions, if it’s not there I re-instate all of them and clone the restored data to recreate the ‘object’. A bit dodgy on restart timing, but it hasn’t failed so far.

Rgds

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [5 September 2019 06:00 UTC](https://discourse.nodered.org/t/persistent-storage-of-global-context/15104/6 "2019-09-05T06:00:23Z")

</div>

> [@rholmesa](#):
>
> useful in development to be able to modify the functions ‘on the fly’ and just save them in the one object

Agreed, you could put them into a single module file without an issue then you can use a "proper" code editor like VScode as well which is nice.

However, you are correct that it can be annoying if you have to restart a lot during development. On my dev machine, Node-RED is started manually via nodemon or PM2 with watches in place so it auto-restarts when certain files like settings.js and external modules change. Helps a little.

> [@rholmesa](#):
>
> As a current workaround, at restart Check for the existence of one of the functions, if it’s not there I re-instate all of them and clone the restored data to recreate the ‘object’. A bit dodgy on restart timing, but it hasn’t failed so far.

You could put it on the first tab with an inject set to go off upon Node-RED startup that creates the object. The first tab always executes first.

Then, once the functions stabilise, move them to a module.

---

<div class="post-metadata">

**Author:** ![rholmesa](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/rholmesa/32/29252_2.png) [@rholmesa](https://discourse.nodered.org/u/rholmesa)\
**Post date:** [18 September 2019 08:40 UTC](https://discourse.nodered.org/t/persistent-storage-of-global-context/15104/7 "2019-09-18T08:40:28Z")

</div>

Ok.  
Tried a few things.  
Still not really getting there though.  
I really wanted to encapsulate the code as part of the object, and I haven't been able to tie this together.

I hasten to add that none of this is a show-stopper, but has become something of a challenge .I would like to resolve over time ...

Currently it is parked. I have a system which works, and it is not being constantly restarted so I can live with minor start up quirks (though honestly I haven't had them yet!).

Thanks for responding.

Regards
