# Deploy modified nodes behavior

**URL:** <https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038>\
**Category:** Developing Nodes\
**Created:** [17 June 2022 05:05 UTC](https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038 "2022-06-17T05:05:15Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![nileio](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nileio/32/9444_2.png) [@nileio](https://discourse.nodered.org/u/nileio)\
**Post date:** [17 June 2022 05:05 UTC](https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038/1 "2022-06-17T05:05:15Z")

</div>

Hi all,  
I have a custom node which uses a number of websocket connections and streams.  
when I use the Full Deploy button , my node and all other nodes restarts as intended. However, when I use Deploy Modified nodes only , I noticed a strange behaviour where I am getting data streams from the old node still.  
When I debugged this I noted that even after the Deploy using Modified Nodes only option, the old config values seem to still linger along side the new config. It is as if I have two versions of the node running at the same time.  
I would have expected that the modified node completely restarts similar to the Full Deploy option, that is references are dropped and node is reset.

```auto
Node-RED version: v2.1.4
Node.js version: v13.10.1

```

Note: I plan to upgrade!

any thoughts or information ?  
Thanks

---

<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:** [17 June 2022 08:13 UTC](https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038/2 "2022-06-17T08:13:09Z")

</div>

We would probably have to look at the code to see what is happening. The first thing to ask though is whether you understand the different parts of a node's runtime and which bits get run when? It isn't necessarily all that obvious until you've thought it through. Kept catching me out on more complex nodes which is why I took the time to de-structure my nodes to make it more obvious to me and to simplify parts of the structure.

---

<div class="post-metadata">

**Author:** ![nileio](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nileio/32/9444_2.png) [@nileio](https://discourse.nodered.org/u/nileio)\
**Post date:** [17 June 2022 13:26 UTC](https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038/3 "2022-06-17T13:26:34Z")

</div>

@TotallyInformation what would be an example of those runtime internals that I need to consider when I use the Deploy Modified nodes only button ? In other words, what is actually happening differently than a Full Deploy ? I dont have knowledge of that

---

<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:** [17 June 2022 16:27 UTC](https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038/4 "2022-06-17T16:27:02Z")

</div>

You need to understand that:

1. There is code outside the `module.exports` which is run when the node is first imported by Node-RED. Any variables and function stay in memory but are not accessible outside your module.

2. The exported code is also run when the node is imported and it is passed the `RED` object. It calls the registration function.

3. The registration function is called each time an actual instance of your node is added to a flow.

4. The `input` event handler is called each time a message is "sent" to your node instance. As the function is defined within (3), it inherits 3's `this` context.

As you can see, there is considerable depth of embedding of functions within each other and it can be hard to understand each context.

That is why I de-construct my nodes to make the divisions easier to parse. You can find an example in my GitHub `node-red-experimental-nodes` repo, check out the `new-node-template` folder. While that structure is certainly more complex than needed for really simple nodes, as your node increases in complexity, it helps keep logical separation between the various moving parts.

---

<div class="post-metadata">

**Author:** ![nileio](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/nileio/32/9444_2.png) [@nileio](https://discourse.nodered.org/u/nileio)\
**Post date:** [2 July 2022 02:09 UTC](https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038/5 "2022-07-02T02:09:37Z")

</div>

@TotallyInformation thank you for taking the time to put this together.

> [@TotallyInformation](#):
>
> There is code outside the `module.exports` which is run when the node is first imported by Node-RED. Any variables and function stay in memory but are not accessible outside your module.

I usually never put any code outside of my `module.exports` scope because I can't think of a use case for this. what would you possibly use this scope for if any at all ? or do you mean the global scope of `module.exports` function ?

> [@TotallyInformation](#):
>
> The registration function is called each time an actual instance of your node is added to a flow.

not sure I am following you here.. the exported function, that is, the `module.exports` function runs on initialisation of the runtime only. It does not run when the node is "added to a flow" , that is just dragged and added to the flow or deployed. It runs with the passed `RED` which is the runtime node-red object giving access to different `utils` including `nodes.registerType` used to register the type. This runs once per node type.

the registration function, that is, the function designated for use as runtime for the instance is called every time the instance is "deployed" to the runtime with the `config`, therefore `this` should be re-initialised every time. the previously deployed instance in runtime should have been discarded at that point, ready to create an instance of the node. then `RED.nodes.createNode` simply applies the config to that instance.

I take the difference between the Full Deploy, and Modified Only to be nothing but either calling every registration function for all nodes or calling only the ones modified.

I would need to put a sample and replicate the behavior but I will see how I go with the new version and if this is a possible issue to report.  
Not sure I maybe missing something but that's OK and thank you as this promoted me to dig bit deeper in the runtime code..

---

<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:** [2 July 2022 14:30 UTC](https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038/6 "2022-07-02T14:30:51Z")

</div>

> [@nileio](#):
>
> I usually never put any code outside of my `module.exports` scope because I can't think of a use case for this. what would you possibly use this scope for if any at all ? or do you mean the global scope of `module.exports` function ?

Things put there are part of your module but are not reachable from the rest of node-red's code or modules. It is a good place to put things that are common to all instances of your nodes. The thing to note is that they are executed _only_ when Node-RED starts up (strictly when node-red loads your module).

In uibuilder for example, that is where I load dependent modules and where I create a common variable object some elements of which are set as the uibuilder node initialises. For example all of the static variables, a copy of the RED object and so on. I also set up the logging function there.

```auto
//#region ------ uibuilder module-level globals ------ //
/** @type {uibConfig} */
const uib = {
    me: fs.readJSONSync(path.join( __dirname, '..', 'package.json' )),
    moduleName: 'uibuilder',
    nodeRoot: '',
    deployments: {},
    instances: {},
    masterTemplateFolder: path.join( __dirname, '..', 'templates' ),
    masterStaticFeFolder: path.join( __dirname, '..', 'front-end' ),
    rootFolder: null,
    configFolder: null,
    configFolderName: '.config',
    commonFolder: null,
    commonFolderName: 'common',
    sioUseMwName: 'sioUse.js',
    sioMsgOutMwName: 'sioMsgOut.js',
    ioChannels: { control: 'uiBuilderControl', client: 'uiBuilderClient', server: 'uiBuilder' },
    nodeVersion: process.version.replace('v', '').split('.'),
    staticOpts: {}, // { maxAge: 31536000, immutable: true, },
    deleteOnDelete: {},
    customServer: { // set correctly in libs/web.js:_webSetup()
        port: undefined,
        type: 'http',
        host: undefined,
        hostName: undefined,
        isCustom: false,
        serverOptions: {},
    },
    reDeployNeeded: '4.1.2',
    degitEmitter: undefined,
    RED: null,
    instanceApiAllowed: false,
}

/** Current module version (taken from package.json) @constant {string} uib.version */
uib.version = uib.me.version

/** Dummy logging
 * @type {Object<string, Function>} */
const dummyLog = {
    fatal: function() {}, // fatal - only those errors which make the application unusable should be recorded
    error: function() {}, // error - record errors which are deemed fatal for a particular request + fatal errors
    warn: function() {}, // warn - record problems which are non fatal + errors + fatal errors
    info: function() {}, // info - record information about the general running of the application + warn + error + fatal errors
    debug: function() {}, // debug - record information which is more verbose than info + info + warn + error + fatal errors
    trace: function() {}, // trace - record very detailed logging + debug + info + warn + error + fatal errors
}
let log = dummyLog // reset to RED.log or anything else you fancy at any point

// Placeholder - set in export
let userDir = ''

//#endregion ----- uibuilder module-level globals ----- //

```

I also set up a bunch of functions there which are then referenced from within the function that actually gets exported.

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

This lets me structure things more logically.

> [@nileio](#):
>
> not sure I am following you here.. the exported function, that is, the `module.exports` function runs on initialisation of the runtime only. It does not run when the node is "added to a flow" , that is just dragged and added to the flow or deployed. It runs with the passed `RED` which is the runtime node-red object giving access to different `utils` including `nodes.registerType` used to register the type. This runs once per node type.

I didn't explain very well. If you look at the above. The function called `nodeInstance` is run for each instance of your node that is added to a flow. It instigates a `this` object and one of the early things you do is run `RED.nodes.createNode(this, config)` which instantiates the `this` as an node instance object. You then assign the settings from the Editor which are passed via the `config` argument to `this` to get the full node instance.

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

Later on, you create the input and close listener functions if you need to.

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

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [31 August 2022 14:31 UTC](https://discourse.nodered.org/t/deploy-modified-nodes-behavior/64038/7 "2022-08-31T14:31:47Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
