diff --git a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js index 6282d1c54..f24f1872a 100644 --- a/packages/node_modules/@node-red/runtime/lib/flows/Flow.js +++ b/packages/node_modules/@node-red/runtime/lib/flows/Flow.js @@ -383,61 +383,51 @@ class Flow { } // Determine the shutdown scope; flows needed to calculate pending msgs - setImmediate(() => { - const seen = new Set(); - const scope = { [this.id]: this }; - const nodes = this.linkNodes.slice(); - seen.add(this.id); - while (nodes.length) { - const node = nodes.pop(); - if (seen.has(node.id)) { - continue; - } - seen.add(node.id); - const flow = activeFlows[node.z]; - if (flow && flow.flow) { - const config = flow.flow.nodes[node.id]; - if (config && config.links) { - config.links.forEach((id) => { - const link = this.getNode(id, false); - if (link && !scope[link._flow.id]) { - scope[link._flow.id] = link._flow; - nodes.push(...link._flow.linkNodes); - } - }); + /** @type {(node: import("@node-red/registry").Node) => boolean} */ + const nodeFilter = (n) => n.type.startsWith("link ") || n.type.startsWith("subflow:"); + const nodes = Object.values(this.flow.nodes || {}).filter(nodeFilter); + const seen = new Set(); + const scope = { [this.id]: true }; + seen.add(this.id); + if (this.subflowInstance && this.subflowInstance.z) { + scope[this.subflowInstance.z] = true; + nodes.push(...Object.values(this.global.flows[this.subflowInstance.z]?.nodes || {}).filter(nodeFilter)); + } + while (nodes.length) { + const node = nodes.pop(); + if (seen.has(node.id)) { + continue; + } + seen.add(node.id); + if (node.links) { + node.links.forEach((id) => { + const link = this.global.allNodes[id]; + if (link && !scope[link.z]) { + scope[link.z] = true; + nodes.push(...Object.values(this.global.flows[link.z]?.nodes || {}).filter(nodeFilter)); } + }) + } else if (node.type.startsWith("subflow:") && !scope[node.id]) { + scope[node.id] = true; + if (!scope[node.type]) { + scope[node.type] = true; + nodes.push(...Object.values(this.global.flows[node.type.substring(8)]?.nodes || {}).filter(nodeFilter)); } } + } - seen.clear(); - const parents = []; - this.shutdownScope = []; - const flows = Object.values(scope); - this._shutdownScope = Object.values(scope); - while (flows.length) { - const flow = flows.pop(); - if (flow && !seen.has(flow.id)) { - seen.add(flow.id); - this.shutdownScope.push(flow); - if (flow.parent.id && flow.parent.id !== "global") { - flows.push(flow.parent); - parents.push(flow.parent); - } - if (flow.subflowInstanceNodes) { - flows.push(...Object.values(flow.subflowInstanceNodes)); - } - } + const scopeList = Object.keys(scope); + this.trace("---------------------------------------------------"); + this.trace(" shutdown scope"); + this.trace("---------------------------------------------------"); + this.trace(scopeList.join(", ")); - } - - // TODO: improve this shit + if (scopeList.length > 1) { setImmediate(() => { - for (const parent of parents) { - this.shutdownScope = [...this.shutdownScope, ...parent._shutdownScope].filter((flow, index, self) => self.indexOf(flow) === index); - } - console.warn(this.id, this.shutdownScope.map(n=>n.id)); - }) - }); + // Lookup for the flow instance + this.shutdownScope = scopeList.map((id) => this.getNode(id, false)?._flow || activeFlows[id]); + }); + } var activeCount = Object.keys(this.activeNodes).length; if (activeCount > 0) {