# A catch with persistent file stores

**URL:** <https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062>\
**Category:** General\
**Created:** [30 January 2020 22:55 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062 "2020-01-30T22:55:47Z")\
**Posts on this page:** 20\
**Page:** 1

<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:** [30 January 2020 22:55 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/1 "2020-01-30T22:55:47Z")

</div>

~~I expect I'm being thick or just tired but~~ I am having a problem with persistent context stores.

No, I'm not being thick, I can see the problem happening. It is because there is a delay of around 30 seconds before persistent variables are written to the fs. While that is fine normally, Node-RED, I think, should flush its cache when stopping but it doesn't.

A bug? Is there a work-around?

* * *

Given the following flow. If I press the top inject, it correctly outputs "fred" from the `flow._test` variable that uses the `file` persistent store. I can press the bottom inject and get the same result as expected.

However, if I press the top inject, then restart Node-RED, the output is `undefined` which is obviously not what I'd expect.

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/9/d907e62b15b3dde3f8ca02f84d0a380055186cbf.png)

```auto
[{"id":"d055686e.e26f28","type":"inject","z":"5cf69d1b.d88c14","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":315,"y":500,"wires":[["1b20e9a0.2000b6"]],"l":false},{"id":"1b20e9a0.2000b6","type":"change","z":"5cf69d1b.d88c14","name":"","rules":[{"t":"set","p":"#:(file)::_test","pt":"flow","to":"fred","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":500,"wires":[["34ef3970.7bb026"]]},{"id":"8f47d888.d531a8","type":"debug","z":"5cf69d1b.d88c14","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":830,"y":500,"wires":[]},{"id":"cdcf8b32.90b248","type":"inject","z":"5cf69d1b.d88c14","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":495,"y":560,"wires":[["34ef3970.7bb026"]],"l":false},{"id":"34ef3970.7bb026","type":"change","z":"5cf69d1b.d88c14","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"#:(file)::_test","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":640,"y":500,"wires":[["8f47d888.d531a8"]]}]

```

And in `settings.js`:

```auto
    contextStorage: {
        default: {
            module:'memory'
        },
        file: {
            module: 'localfilesystem'
        }
    },

```

```auto
30 Jan 22:37:08 - [info] Node-RED version: v1.0.3
30 Jan 22:37:08 - [info] Node.js version: v12.14.0
30 Jan 22:37:08 - [info] Windows_NT 10.0.18363 x64 LE

```

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/2/2220effbcaafa14a4853a055d544d6602f2ed1b1.png)

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/5/b5421aaa9ebc9313b646e93030aba71cf505fb0d.png)

* * *

Incidentally, you can see the same thing just by using the context sidebar. Write to a flow variable (it happens with flow, node and global). Wait 30 sec. Then delete the variable using the icon in the sidebar and either stop the Node-RED process or restart it within 30 sec. When you restart, the variable will still be there.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [30 January 2020 23:03 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/2 "2020-01-30T23:03:38Z")

</div>

You can always change the flush interval;

```auto
    contextStorage: {
      default: "file",
    memoryOnly: { module: 'memory' },
          file: { module: 'localfilesystem',
          config: {
                  flushInterval: '10'
                  },
           },
    },
```

---

<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:** [30 January 2020 23:04 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/3 "2020-01-30T23:04:16Z")

</div>

How are you stopping Node-RED? If you are just killing the process abruptly, then you don't allow the file store to flush it's contents.

---

<div class="post-metadata">

**Author:** ![drmibell](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/drmibell/32/8424_2.png) [@drmibell](https://discourse.nodered.org/u/drmibell)\
**Post date:** [30 January 2020 23:32 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/4 "2020-01-30T23:32:53Z")

</div>

This issue seems to have come up [before](https://discourse.nodered.org/t/persistent-data-not-being-saved/5680), and presumably was [resolved](https://github.com/node-red/node-red/issues/2001) in version 0.20. Or is this something new?

---

<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:** [30 January 2020 23:38 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/5 "2020-01-30T23:38:04Z")

</div>

> [@Paul-Reed](#):
>
> You can always change the flush interval;

Thanks for the reminder.

> [@knolleary](#):
>
> How are you stopping Node-RED? If you are just killing the process abruptly, then you don't allow the file store to flush it's contents.

Well, I'm mainly using nodemon so I'd expect it is sending a signal to the process.

I think that the point is that I believe that Node.js is capable of trapping such signals and doing some minor process before exit? Can't say that I really understand it but that's what I thought.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [30 January 2020 23:50 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/6 "2020-01-30T23:50:12Z")

</div>

What signal does nodemon use to kill the process ?

---

<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:** [31 January 2020 00:29 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/7 "2020-01-31T00:29:18Z")

</div>

You had to go and ask didn't you!

Well a quick look through the code found this:

```auto
const restartSignal = config.options.signal === 'SIGUSR2' ? 'SIGHUP' : 'SIGUSR2';

```

There may be more, I'll look further.

And there is a bunch of code around here that looks like it is using kill with a signal code:

> <https://github.com/remy/nodemon/blob/master/lib/monitor/run.js#L358>

I think that I was expecting Node-RED do something like this to clean up:

> <https://stackoverflow.com/questions/14031763/doing-a-cleanup-action-just-before-node-js-exits/14032965#14032965>

* * *

Obviously, as things stand, all the talk about using persistent context stores is on somewhat shaky ground if you have to be sure that your server continues to process for 30 seconds after you can something. A full deploy, for example, might wipe out an incoming update but might appear to be inconsistent (which I how I came across this).

Given the earlier discussions about this area and core processing, I'd be reluctant to add signal processing to my own code even if there was some kind of flush function for the storage modal - though this would certainly be one option.

I don't think that `node.on('close', function(removed,done) { ... }` is processing during this kind of exit either? Certainly, I don't get any `console.log` output from that function.

I'm also reluctant to change the `flushInterval` as per Paul's code as I'm not sure of the performance impact and it relies on users/administrators making changes to `settings.js` in a particular way.

---

<div class="post-metadata">

**Author:** ![Paul-Reed](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/paul-reed/32/66906_2.png) [@Paul-Reed](https://discourse.nodered.org/u/Paul-Reed)\
**Post date:** [31 January 2020 09:29 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/8 "2020-01-31T09:29:36Z")

</div>

> [@TotallyInformation](#):
>
> I'm also reluctant to change the `flushInterval` as per Paul's code as I'm not sure of the performance impac

I've actually increased my flush interval for my pi (running on a SD card).

I've just tested whether my 'script installed' installation of node-RED writes it's cache upon shutdown/restart, and yes it does & works as expected with the following commands;  
`node-red-stop`  
`node-red-restart`  
`sudo poweroff`  
`sudo shutdown`

---

<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:** [31 January 2020 10:07 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/9 "2020-01-31T10:07:51Z")

</div>

It's good to know when it does and doesn't so we probably need to create a full list for the documentation so that people don't get caught out.

Thanks for doing that research Paul.

I realise that my use-case is rather "edge" (typically me) but I think people should at least be aware.

I do also think that Node-RED potentially _could_ trap other signals in order to close this gap though I appreciate that this is not likely to be high on the priority list.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [31 January 2020 10:17 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/10 "2020-01-31T10:17:31Z")

</div>

Julian at the bottom of red.js we have

process.on('SIGINT', function () {...

can you try just duplicating that block and changing one to SIGUSR2 ?

---

<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:** [31 January 2020 10:18 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/11 "2020-01-31T10:18:37Z")

</div>

The docs do already say this:

> The `flushInterval` is provided to minimise wear on the underlying storage, such as on a Raspberry Pi’s SD card. **Note that if Node-RED is unexpectedly killed, any data that has not yet been flushed will be lost.**

[https://nodered.org/docs/api/context/store/localfilesystem#options](https://nodered.org/docs/api/context/store/localfilesystem#options)

If you feel it could say more, then please do raise a PR with a proposal.

---

<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:** [31 January 2020 10:21 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/12 "2020-01-31T10:21:57Z")

</div>

> [@dceejay](#):
>
> can you try just duplicating that block and changing one to SIGUSR2

Thanks Dave, started to add something along those lines - will test when I get a chance and let you know.

> [@knolleary](#):
>
> If you feel it could say more, then please do raise a PR with a proposal.

Thanks Nick. Perhaps needs something a bit more detailed as an addendum but lets see where we get to with the details first.

---

<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:** [31 January 2020 10:22 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/13 "2020-01-31T10:22:50Z")

</div>

Title changed as I don't want to imply this is Node-RED's problem.

---

<div class="post-metadata">

**Author:** ![cymplecy](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/cymplecy/32/2773_2.png) [@cymplecy](https://discourse.nodered.org/u/cymplecy)\
**Post date:** [31 January 2020 10:32 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/14 "2020-01-31T10:32:56Z")

</div>

> [@TotallyInformation](#):
>
> However, if I press the top inject, then restart Node-RED, the output is `undefined`

Alternatively - just go for a cup of tea or do 20 push-ups before closing Node-RED.......

---

<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:** [31 January 2020 10:36 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/15 "2020-01-31T10:36:31Z")

</div>

An excellent idea Simon - though coffee is my poison.

However, it does rather slow down the development process 😀

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [31 January 2020 10:47 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/16 "2020-01-31T10:47:26Z")

</div>

I think it is the SIGUSR2... By default we catch SIGINT - which is usual ctrl-c - break etc.... so we probably just need to expand that list sensibly... (eg probably shouldn't interrupt a SIGKILL)

probably....

---

<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:** [31 January 2020 11:44 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/17 "2020-01-31T11:44:55Z")

</div>

> [@dceejay](#):
>
> process.on('SIGINT', function ()

I don't think Node.js allows you to catch SIGKILL anyway.

I added the following to the end of red.js as I couldn't see it doing anything in my own code:

```auto
process.on('SIGUSR1', function () {
    util.log('[RED] === SIGUSR1 ===')
    RED.stop().then(function() {
        process.exit();
    });
});

process.on('SIGUSR2', function () {
    util.log('[RED] === SIGUSR2 ===')
    RED.stop().then(function() {
        process.exit();
    });
});

process.on('SIGHUP', function () {
    util.log('[RED] === SIGHUP ===')
    RED.stop().then(function() {
        process.exit();
    });
});

```

And it did nothing!

Not only do none of those actually get caught by restarting in nodemon or issuing a `kill`, but the `SIGINT` catch doesn't help since the context store isn't written back anyway at least in the 3-5 second test that I've done so far.

Another caveat on my testing so far, I've only tested on Windows 10, I've not yet tried on the Pi and I'd like to because I know that stream handling can be slightly different between the 2.

I need to get back to my day-job now, I'll try and do some more testing over the weekend.

* * *

One other thing I noted when looking at `red.js`, you are using `util.log` which has been deprecated since Node.js v6 so I imagine that it will be removed at some point.

Also, the SIGINT processing is supposed to be synchronous and I'm not sure that processing `RED.stop()` is since it is promise based? I don't know enough about it to say though.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [31 January 2020 13:08 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/18 "2020-01-31T13:08:20Z")

</div>

util.log is our own version I think (see requires at top of file...) - but just try console.log instead.  
If I also add some to packages/node\_modules/@node-red/runtime/lib/nodes/context/localfilesystem.js around line 233 I can see it gets called before exiting.

---

<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:** [31 January 2020 13:55 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/19 "2020-01-31T13:55:12Z")

</div>

Some of this may be a Windows/Node.js thing. Output to stdout on Windows is async but to file is sync. according to the docs. Which is why I also need to try this on the Pi.

Thanks for the references to the code by the way. I can use this as an excuse to learn some more about the core code.

I might even have some fun taking a copy of the localfilingsystem module and creating a custom one - be better than risking breaking my dev Node-RED installation 🙂 Also then easier to test on one of the Pi's.

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [31 January 2020 14:20 UTC](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062/20 "2020-01-31T14:20:42Z")

</div>

net is I think we may need to also catch a few of the other signals...  
SIGINT (as today), SIGTERM, SIGHUP and SIGUSR2

any more thoughts ?

[Next page](https://discourse.nodered.org/t/a-catch-with-persistent-file-stores/21062.md?page=2)
