mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Rework start/stop api to use runtime-event notification message
This commit is contained in:
parent
68c1e49f62
commit
f33848e16b
@ -83,7 +83,7 @@ module.exports = {
|
|||||||
postState: function(req,res) {
|
postState: function(req,res) {
|
||||||
const opts = {
|
const opts = {
|
||||||
user: req.user,
|
user: req.user,
|
||||||
requestedState: req.body.state||"",
|
state: req.body.state || "",
|
||||||
req: apiUtils.getRequestLogObject(req)
|
req: apiUtils.getRequestLogObject(req)
|
||||||
}
|
}
|
||||||
runtimeAPI.flows.setState(opts).then(function(result) {
|
runtimeAPI.flows.setState(opts).then(function(result) {
|
||||||
|
@ -169,6 +169,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"notification": {
|
"notification": {
|
||||||
|
"state": {
|
||||||
|
"flowsStopped": "Flows stopped",
|
||||||
|
"flowsStarted": "Flows started"
|
||||||
|
},
|
||||||
"warning": "<strong>Warning</strong>: __message__",
|
"warning": "<strong>Warning</strong>: __message__",
|
||||||
"warnings": {
|
"warnings": {
|
||||||
"undeployedChanges": "node has undeployed changes",
|
"undeployedChanges": "node has undeployed changes",
|
||||||
@ -291,12 +295,6 @@
|
|||||||
"stopstart":{
|
"stopstart":{
|
||||||
"status": {
|
"status": {
|
||||||
"state_changed": "Flows runtime has been changed to '__state__' state"
|
"state_changed": "Flows runtime has been changed to '__state__' state"
|
||||||
},
|
|
||||||
"errors": {
|
|
||||||
"notAllowed": "Method not allowed",
|
|
||||||
"notAuthorized": "Not authorized",
|
|
||||||
"notFound": "Not found",
|
|
||||||
"noResponse": "No response from server"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"deploy": {
|
"deploy": {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Interface to nodes and utility functions for creating/adding/deleting nodes and links
|
* An Interface to nodes and utility functions for creating/adding/deleting nodes and links
|
||||||
* @namespace RED.nodes
|
* @namespace RED.nodes
|
||||||
*/
|
*/
|
||||||
|
@ -336,7 +336,6 @@ var RED = (function() {
|
|||||||
id: notificationId
|
id: notificationId
|
||||||
}
|
}
|
||||||
if (notificationId === "runtime-state") {
|
if (notificationId === "runtime-state") {
|
||||||
RED.events.emit("runtime-state",msg);
|
|
||||||
if (msg.error === "safe-mode") {
|
if (msg.error === "safe-mode") {
|
||||||
options.buttons = [
|
options.buttons = [
|
||||||
{
|
{
|
||||||
@ -477,9 +476,9 @@ var RED = (function() {
|
|||||||
} else if (persistentNotifications.hasOwnProperty(notificationId)) {
|
} else if (persistentNotifications.hasOwnProperty(notificationId)) {
|
||||||
persistentNotifications[notificationId].close();
|
persistentNotifications[notificationId].close();
|
||||||
delete persistentNotifications[notificationId];
|
delete persistentNotifications[notificationId];
|
||||||
if (notificationId === 'runtime-state') {
|
}
|
||||||
RED.events.emit("runtime-state",msg);
|
if (notificationId === 'runtime-state') {
|
||||||
}
|
RED.events.emit("runtime-state",msg);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
RED.comms.subscribe("status/#",function(topic,msg) {
|
RED.comms.subscribe("status/#",function(topic,msg) {
|
||||||
|
@ -1,53 +1,36 @@
|
|||||||
RED.runtime = (function() {
|
RED.runtime = (function() {
|
||||||
let state = ""
|
let state = ""
|
||||||
let settings = {ui: false, enabled: false};
|
let settings = { ui: false, enabled: false };
|
||||||
const STOPPED = "stopped"
|
const STOPPED = "stop"
|
||||||
const STARTED = "started"
|
const STARTED = "start"
|
||||||
|
const SAFE = "safe"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init: function() {
|
init: function() {
|
||||||
// refresh the current runtime status from server
|
// refresh the current runtime status from server
|
||||||
settings = Object.assign({}, settings, RED.settings.runtimeState);
|
settings = Object.assign({}, settings, RED.settings.runtimeState);
|
||||||
RED.runtime.requestState()
|
RED.events.on("runtime-state", function(msg) {
|
||||||
|
if (msg.state) {
|
||||||
// {id:"flows-run-state", started: false, state: "stopped", retain:true}
|
const currentState = state
|
||||||
RED.comms.subscribe("notification/flows-run-state",function(topic,msg) {
|
state = msg.state
|
||||||
RED.events.emit("flows-run-state",msg);
|
$(".red-ui-flow-node-button").toggleClass("red-ui-flow-node-button-stopped", state !== STARTED)
|
||||||
RED.runtime.updateState(msg.state);
|
if(settings.enabled === true && settings.ui === true) {
|
||||||
});
|
RED.menu.setVisible("deploymenu-item-runtime-stop", state === STARTED)
|
||||||
},
|
RED.menu.setVisible("deploymenu-item-runtime-start", state !== STARTED)
|
||||||
get state() {
|
}
|
||||||
return state
|
// Do not notify the user about this event if:
|
||||||
},
|
// - This is the very first event we've received after loading the editor (currentState = '')
|
||||||
get started() {
|
// - The state matches what we already thought was the case (state === currentState)
|
||||||
return state === STARTED
|
// - The event was triggered by a deploy (msg.deploy === true)
|
||||||
},
|
// - The event is a safe mode event - that gets notified separately
|
||||||
get states() {
|
if (currentState !== '' && state !== currentState && !msg.deploy && state !== SAFE) {
|
||||||
return { STOPPED, STARTED }
|
RED.notify(RED._("notification.state.flows"+(state === STOPPED?'Stopped':'Started'), msg), "success")
|
||||||
},
|
|
||||||
updateState: function(newState) {
|
|
||||||
state = newState;
|
|
||||||
// disable pointer events on node buttons (e.g. inject/debug nodes)
|
|
||||||
$(".red-ui-flow-node-button").toggleClass("red-ui-flow-node-button-stopped", state === STOPPED)
|
|
||||||
// show/hide Start/Stop based on current state
|
|
||||||
if(settings.enabled === true && settings.ui === true) {
|
|
||||||
RED.menu.setVisible("deploymenu-item-runtime-stop", state === STARTED)
|
|
||||||
RED.menu.setVisible("deploymenu-item-runtime-start", state === STOPPED)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
requestState: function(callback) {
|
|
||||||
$.ajax({
|
|
||||||
headers: {
|
|
||||||
"Accept":"application/json"
|
|
||||||
},
|
|
||||||
cache: false,
|
|
||||||
url: 'flows/state',
|
|
||||||
success: function(data) {
|
|
||||||
RED.runtime.updateState(data.state)
|
|
||||||
if(callback) {
|
|
||||||
callback(data.state)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
get started() {
|
||||||
|
return state === STARTED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
@ -69,7 +69,7 @@ RED.deploy = (function() {
|
|||||||
{id:"deploymenu-item-node",toggle:"deploy-type",icon:"red/images/deploy-nodes.svg",label:RED._("deploy.modifiedNodes"),sublabel:RED._("deploy.modifiedNodesDesc"),onselect:function(s) { if(s){changeDeploymentType("nodes")}}},
|
{id:"deploymenu-item-node",toggle:"deploy-type",icon:"red/images/deploy-nodes.svg",label:RED._("deploy.modifiedNodes"),sublabel:RED._("deploy.modifiedNodesDesc"),onselect:function(s) { if(s){changeDeploymentType("nodes")}}},
|
||||||
null
|
null
|
||||||
]
|
]
|
||||||
if(RED.settings.runtimeState && RED.settings.runtimeState.ui === true) {
|
if (RED.settings.runtimeState && RED.settings.runtimeState.ui === true) {
|
||||||
mainMenuItems.push({id:"deploymenu-item-runtime-start", icon:"red/images/start.svg",label:"Start"/*RED._("deploy.startFlows")*/,sublabel:"Start Flows" /*RED._("deploy.startFlowsDesc")*/,onselect:"core:start-flows", visible:false})
|
mainMenuItems.push({id:"deploymenu-item-runtime-start", icon:"red/images/start.svg",label:"Start"/*RED._("deploy.startFlows")*/,sublabel:"Start Flows" /*RED._("deploy.startFlowsDesc")*/,onselect:"core:start-flows", visible:false})
|
||||||
mainMenuItems.push({id:"deploymenu-item-runtime-stop", icon:"red/images/stop.svg",label:"Stop"/*RED._("deploy.startFlows")*/,sublabel:"Stop Flows" /*RED._("deploy.startFlowsDesc")*/,onselect:"core:stop-flows", visible:false})
|
mainMenuItems.push({id:"deploymenu-item-runtime-stop", icon:"red/images/stop.svg",label:"Stop"/*RED._("deploy.startFlows")*/,sublabel:"Stop Flows" /*RED._("deploy.startFlowsDesc")*/,onselect:"core:stop-flows", visible:false})
|
||||||
}
|
}
|
||||||
@ -302,7 +302,6 @@ RED.deploy = (function() {
|
|||||||
deployInflight = true
|
deployInflight = true
|
||||||
deployButtonSetBusy()
|
deployButtonSetBusy()
|
||||||
shadeShow()
|
shadeShow()
|
||||||
RED.runtime.updateState(state)
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url:"flows/state",
|
url:"flows/state",
|
||||||
type: "POST",
|
type: "POST",
|
||||||
@ -311,30 +310,23 @@ RED.deploy = (function() {
|
|||||||
if (deployWasEnabled) {
|
if (deployWasEnabled) {
|
||||||
$("#red-ui-header-button-deploy").removeClass("disabled")
|
$("#red-ui-header-button-deploy").removeClass("disabled")
|
||||||
}
|
}
|
||||||
RED.runtime.updateState((data && data.state) || "unknown")
|
|
||||||
RED.notify(RED._("stopstart.status.state_changed", data), "success")
|
|
||||||
}).fail(function(xhr,textStatus,err) {
|
}).fail(function(xhr,textStatus,err) {
|
||||||
if (deployWasEnabled) {
|
if (deployWasEnabled) {
|
||||||
$("#red-ui-header-button-deploy").removeClass("disabled")
|
$("#red-ui-header-button-deploy").removeClass("disabled")
|
||||||
}
|
}
|
||||||
if (xhr.status === 401) {
|
if (xhr.status === 401) {
|
||||||
RED.notify(RED._("notification.error", { message: RED._("stopstart.errors.notAuthorized") }), "error")
|
RED.notify(RED._("notification.error", { message: RED._("user.notAuthorized") }), "error")
|
||||||
} else if (xhr.status === 404) {
|
|
||||||
RED.notify(RED._("notification.error", { message: RED._("stopstart.errors.notFound") }), "error")
|
|
||||||
} else if (xhr.status === 405) {
|
|
||||||
RED.notify(RED._("notification.error", { message: RED._("stopstart.errors.notAllowed") }), "error")
|
|
||||||
} else if (xhr.responseText) {
|
} else if (xhr.responseText) {
|
||||||
const errorDetail = { message: err ? (err + "") : "" }
|
const errorDetail = { message: err ? (err + "") : "" }
|
||||||
try {
|
try {
|
||||||
errorDetail.message = JSON.parse(xhr.responseText).message
|
errorDetail.message = JSON.parse(xhr.responseText).message
|
||||||
} finally {
|
} finally {
|
||||||
errorDetail.message = errorDetail.message || xhr.responseText
|
errorDetail.message = errorDetail.message || xhr.responseText
|
||||||
}
|
}
|
||||||
RED.notify(RED._("notification.error", errorDetail), "error")
|
RED.notify(RED._("notification.error", errorDetail), "error")
|
||||||
} else {
|
} else {
|
||||||
RED.notify(RED._("notification.error", { message: RED._("stopstart.errors.noResponse") }), "error")
|
RED.notify(RED._("notification.error", { message: RED._("deploy.errors.noResponse") }), "error")
|
||||||
}
|
}
|
||||||
RED.runtime.requestState()
|
|
||||||
}).always(function() {
|
}).always(function() {
|
||||||
const delta = Math.max(0, 300 - (Date.now() - startTime))
|
const delta = Math.max(0, 300 - (Date.now() - startTime))
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
@ -514,13 +506,10 @@ RED.deploy = (function() {
|
|||||||
|
|
||||||
deployButtonSetBusy();
|
deployButtonSetBusy();
|
||||||
const data = { flows: nns };
|
const data = { flows: nns };
|
||||||
data.runtimeState = RED.runtime.state;
|
if (!force) {
|
||||||
if (data.runtimeState === RED.runtime.states.STOPPED || force) {
|
|
||||||
data._rev = RED.nodes.version();
|
|
||||||
} else {
|
|
||||||
data.rev = RED.nodes.version();
|
data.rev = RED.nodes.version();
|
||||||
}
|
}
|
||||||
|
|
||||||
deployInflight = true;
|
deployInflight = true;
|
||||||
shadeShow();
|
shadeShow();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -4877,7 +4877,7 @@ RED.view = (function() {
|
|||||||
if (d._def.button) {
|
if (d._def.button) {
|
||||||
var buttonEnabled = isButtonEnabled(d);
|
var buttonEnabled = isButtonEnabled(d);
|
||||||
this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-disabled", !buttonEnabled);
|
this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-disabled", !buttonEnabled);
|
||||||
if(RED.runtime && Object.hasOwn(RED.runtime,'started')) {
|
if (RED.runtime && Object.hasOwn(RED.runtime,'started')) {
|
||||||
this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-stopped", !RED.runtime.started);
|
this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-stopped", !RED.runtime.started);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,10 +73,6 @@ var api = module.exports = {
|
|||||||
if (deploymentType === 'reload') {
|
if (deploymentType === 'reload') {
|
||||||
apiPromise = runtime.flows.loadFlows(true);
|
apiPromise = runtime.flows.loadFlows(true);
|
||||||
} else {
|
} else {
|
||||||
//ensure the runtime running/stopped state matches the deploying editor. If not, then copy the _rev number to flows.rev
|
|
||||||
if(flows.hasOwnProperty('_rev') && !flows.hasOwnProperty('rev') && (flows.runtimeState !== "stopped" || runtime.flows.started)) {
|
|
||||||
flows.rev = flows._rev
|
|
||||||
}
|
|
||||||
if (flows.hasOwnProperty('rev')) {
|
if (flows.hasOwnProperty('rev')) {
|
||||||
var currentVersion = runtime.flows.getFlows().rev;
|
var currentVersion = runtime.flows.getFlows().rev;
|
||||||
if (currentVersion !== flows.rev) {
|
if (currentVersion !== flows.rev) {
|
||||||
@ -271,9 +267,7 @@ var api = module.exports = {
|
|||||||
getState: async function(opts) {
|
getState: async function(opts) {
|
||||||
runtime.log.audit({event: "flows.getState"}, opts.req);
|
runtime.log.audit({event: "flows.getState"}, opts.req);
|
||||||
const result = {
|
const result = {
|
||||||
state: runtime.flows.started ? "started" : "stopped",
|
state: runtime.flows.state()
|
||||||
started: !!runtime.flows.started,
|
|
||||||
rev: runtime.flows.getFlows().rev
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
@ -282,7 +276,7 @@ var api = module.exports = {
|
|||||||
* @param {Object} opts
|
* @param {Object} opts
|
||||||
* @param {Object} opts.req - the request to log (optional)
|
* @param {Object} opts.req - the request to log (optional)
|
||||||
* @param {User} opts.user - the user calling the api
|
* @param {User} opts.user - the user calling the api
|
||||||
* @param {string} opts.requestedState - the requested state. Valid values are "start" and "stop".
|
* @param {string} opts.state - the requested state. Valid values are "start" and "stop".
|
||||||
* @return {Promise<Flow>} - the active flow configuration
|
* @return {Promise<Flow>} - the active flow configuration
|
||||||
* @memberof @node-red/runtime_flows
|
* @memberof @node-red/runtime_flows
|
||||||
*/
|
*/
|
||||||
@ -295,7 +289,7 @@ var api = module.exports = {
|
|||||||
err.code = err.code || errcode || "unexpected_error"
|
err.code = err.code || errcode || "unexpected_error"
|
||||||
runtime.log.audit({
|
runtime.log.audit({
|
||||||
event: "flows.setState",
|
event: "flows.setState",
|
||||||
state: opts.requestedState || "",
|
state: opts.state || "",
|
||||||
error: errcode || "unexpected_error",
|
error: errcode || "unexpected_error",
|
||||||
message: err.code
|
message: err.code
|
||||||
}, opts.req);
|
}, opts.req);
|
||||||
@ -304,21 +298,22 @@ var api = module.exports = {
|
|||||||
|
|
||||||
const getState = () => {
|
const getState = () => {
|
||||||
return {
|
return {
|
||||||
state: runtime.flows.started ? "started" : "stopped",
|
state: runtime.flows.state()
|
||||||
started: !!runtime.flows.started,
|
|
||||||
rev: runtime.flows.getFlows().rev,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!runtime.settings.runtimeState || runtime.settings.runtimeState.enabled !== true) {
|
if(!runtime.settings.runtimeState || runtime.settings.runtimeState.enabled !== true) {
|
||||||
throw (makeError("Method Not Allowed", "not_allowed", 405))
|
throw (makeError("Method Not Allowed", "not_allowed", 405))
|
||||||
}
|
}
|
||||||
switch (opts.requestedState) {
|
switch (opts.state) {
|
||||||
case "start":
|
case "start":
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
runtime.settings.set('flowsRunStateRequested', opts.requestedState);
|
runtime.settings.set('runtimeFlowState', opts.state);
|
||||||
} catch(err) { }
|
} catch(err) {}
|
||||||
|
if (runtime.settings.safeMode) {
|
||||||
|
delete runtime.settings.safeMode
|
||||||
|
}
|
||||||
await runtime.flows.startFlows("full")
|
await runtime.flows.startFlows("full")
|
||||||
return getState()
|
return getState()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -327,15 +322,15 @@ var api = module.exports = {
|
|||||||
case "stop":
|
case "stop":
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
runtime.settings.set('flowsRunStateRequested', opts.requestedState);
|
runtime.settings.set('runtimeFlowState', opts.state);
|
||||||
} catch(err) { }
|
} catch(err) {}
|
||||||
await runtime.flows.stopFlows("full")
|
await runtime.flows.stopFlows("full")
|
||||||
return getState()
|
return getState()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw (makeError(err, err.code, 500))
|
throw (makeError(err, err.code, 500))
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw (makeError(`Cannot change flows runtime state to '${opts.requestedState}'}`, "invalid_run_state", 400))
|
throw (makeError(`Cannot change flows runtime state to '${opts.state}'}`, "invalid_run_state", 400))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@ var activeFlowConfig = null;
|
|||||||
|
|
||||||
var activeFlows = {};
|
var activeFlows = {};
|
||||||
var started = false;
|
var started = false;
|
||||||
|
var state = 'stop'
|
||||||
|
|
||||||
var credentialsPendingReset = false;
|
var credentialsPendingReset = false;
|
||||||
|
|
||||||
var activeNodesToFlow = {};
|
var activeNodesToFlow = {};
|
||||||
@ -50,6 +52,7 @@ function init(runtime) {
|
|||||||
storage = runtime.storage;
|
storage = runtime.storage;
|
||||||
log = runtime.log;
|
log = runtime.log;
|
||||||
started = false;
|
started = false;
|
||||||
|
state = 'stop';
|
||||||
if (!typeEventRegistered) {
|
if (!typeEventRegistered) {
|
||||||
events.on('type-registered',function(type) {
|
events.on('type-registered',function(type) {
|
||||||
if (activeFlowConfig && activeFlowConfig.missingTypes.length > 0) {
|
if (activeFlowConfig && activeFlowConfig.missingTypes.length > 0) {
|
||||||
@ -214,19 +217,26 @@ function setFlows(_config,_credentials,type,muteLog,forceStart,user) {
|
|||||||
// Flows are running (or should be)
|
// Flows are running (or should be)
|
||||||
|
|
||||||
// Stop the active flows (according to deploy type and the diff)
|
// Stop the active flows (according to deploy type and the diff)
|
||||||
return stop(type,diff,muteLog).then(() => {
|
return stop(type,diff,muteLog,true).then(() => {
|
||||||
// Once stopped, allow context to remove anything no longer needed
|
// Once stopped, allow context to remove anything no longer needed
|
||||||
return context.clean(activeFlowConfig)
|
return context.clean(activeFlowConfig)
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
if (!isLoad) {
|
||||||
|
log.info(log._("nodes.flows.updated-flows"));
|
||||||
|
}
|
||||||
// Start the active flows
|
// Start the active flows
|
||||||
start(type,diff,muteLog).then(() => {
|
start(type,diff,muteLog,true).then(() => {
|
||||||
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
|
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
|
||||||
});
|
});
|
||||||
// Return the new revision asynchronously to the actual start
|
// Return the new revision asynchronously to the actual start
|
||||||
return flowRevision;
|
return flowRevision;
|
||||||
}).catch(function(err) { })
|
}).catch(function(err) { })
|
||||||
} else {
|
} else {
|
||||||
|
if (!isLoad) {
|
||||||
|
log.info(log._("nodes.flows.updated-flows"));
|
||||||
|
}
|
||||||
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
|
events.emit("runtime-event",{id:"runtime-deploy",payload:{revision:flowRevision},retain: true});
|
||||||
|
return flowRevision;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -259,10 +269,10 @@ function getFlows() {
|
|||||||
return activeConfig;
|
return activeConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function start(type,diff,muteLog) {
|
async function start(type,diff,muteLog,isDeploy) {
|
||||||
type = type||"full";
|
type = type || "full";
|
||||||
let reallyStarted = started
|
|
||||||
started = true;
|
started = true;
|
||||||
|
state = 'start'
|
||||||
var i;
|
var i;
|
||||||
// If there are missing types, report them, emit the necessary runtime event and return
|
// If there are missing types, report them, emit the necessary runtime event and return
|
||||||
if (activeFlowConfig.missingTypes.length > 0) {
|
if (activeFlowConfig.missingTypes.length > 0) {
|
||||||
@ -284,7 +294,7 @@ async function start(type,diff,muteLog) {
|
|||||||
log.info(log._("nodes.flows.missing-type-install-2"));
|
log.info(log._("nodes.flows.missing-type-install-2"));
|
||||||
log.info(" "+settings.userDir);
|
log.info(" "+settings.userDir);
|
||||||
}
|
}
|
||||||
events.emit("runtime-event",{id:"runtime-state",payload:{error:"missing-types", type:"warning",text:"notification.warnings.missing-types",types:activeFlowConfig.missingTypes},retain:true});
|
events.emit("runtime-event",{id:"runtime-state",payload:{state: 'stop', error:"missing-types", type:"warning",text:"notification.warnings.missing-types",types:activeFlowConfig.missingTypes},retain:true});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +308,7 @@ async function start(type,diff,muteLog) {
|
|||||||
missingModules.push({module:err[i].module.module, error: err[i].error.code || err[i].error.toString()})
|
missingModules.push({module:err[i].module.module, error: err[i].error.code || err[i].error.toString()})
|
||||||
log.info(` - ${err[i].module.spec} [${err[i].error.code || "unknown_error"}]`);
|
log.info(` - ${err[i].module.spec} [${err[i].error.code || "unknown_error"}]`);
|
||||||
}
|
}
|
||||||
events.emit("runtime-event",{id:"runtime-state",payload:{error:"missing-modules", type:"warning",text:"notification.warnings.missing-modules",modules:missingModules},retain:true});
|
events.emit("runtime-event",{id:"runtime-state",payload:{state: 'stop', error:"missing-modules", type:"warning",text:"notification.warnings.missing-modules",modules:missingModules},retain:true});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,10 +317,20 @@ async function start(type,diff,muteLog) {
|
|||||||
log.info("*****************************************************************")
|
log.info("*****************************************************************")
|
||||||
log.info(log._("nodes.flows.safe-mode"));
|
log.info(log._("nodes.flows.safe-mode"));
|
||||||
log.info("*****************************************************************")
|
log.info("*****************************************************************")
|
||||||
events.emit("runtime-event",{id:"runtime-state",payload:{error:"safe-mode", type:"warning",text:"notification.warnings.safe-mode"},retain:true});
|
state = 'safe'
|
||||||
|
events.emit("runtime-event",{id:"runtime-state",payload:{state: 'safe', error:"safe-mode", type:"warning",text:"notification.warnings.safe-mode"},retain:true});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const runtimeState = settings.get('runtimeFlowState') || 'start'
|
||||||
|
if (runtimeState === 'stop') {
|
||||||
|
log.info(log._("nodes.flows.stopped-flows"));
|
||||||
|
events.emit("runtime-event",{id:"runtime-state",payload:{ state: 'stop', deploy:isDeploy },retain:true});
|
||||||
|
state = 'stop'
|
||||||
|
started = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (!muteLog) {
|
if (!muteLog) {
|
||||||
if (type !== "full") {
|
if (type !== "full") {
|
||||||
log.info(log._("nodes.flows.starting-modified-"+type));
|
log.info(log._("nodes.flows.starting-modified-"+type));
|
||||||
@ -365,51 +385,31 @@ async function start(type,diff,muteLog) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Having created or updated all flows, now start them.
|
for (id in activeFlows) {
|
||||||
let startFlows = true
|
if (activeFlows.hasOwnProperty(id)) {
|
||||||
try {
|
try {
|
||||||
startFlows = settings.get('flowsRunStateRequested');
|
activeFlows[id].start(diff);
|
||||||
} catch(err) {
|
// Create a map of node id to flow id and also a subflowInstance lookup map
|
||||||
}
|
var activeNodes = activeFlows[id].getActiveNodes();
|
||||||
startFlows = (startFlows !== "stop");
|
Object.keys(activeNodes).forEach(function(nid) {
|
||||||
|
activeNodesToFlow[nid] = id;
|
||||||
if (startFlows) {
|
});
|
||||||
for (id in activeFlows) {
|
} catch(err) {
|
||||||
if (activeFlows.hasOwnProperty(id)) {
|
console.log(err.stack);
|
||||||
try {
|
|
||||||
activeFlows[id].start(diff);
|
|
||||||
// Create a map of node id to flow id and also a subflowInstance lookup map
|
|
||||||
var activeNodes = activeFlows[id].getActiveNodes();
|
|
||||||
Object.keys(activeNodes).forEach(function(nid) {
|
|
||||||
activeNodesToFlow[nid] = id;
|
|
||||||
});
|
|
||||||
} catch(err) {
|
|
||||||
console.log(err.stack);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reallyStarted = true;
|
|
||||||
events.emit("flows:started", {config: activeConfig, type: type, diff: diff});
|
|
||||||
// Deprecated event
|
|
||||||
events.emit("nodes-started");
|
|
||||||
} else {
|
|
||||||
started = false;
|
|
||||||
}
|
}
|
||||||
|
events.emit("flows:started", {config: activeConfig, type: type, diff: diff});
|
||||||
const state = {
|
// Deprecated event
|
||||||
started: reallyStarted,
|
events.emit("nodes-started");
|
||||||
state: reallyStarted ? "started" : "stopped",
|
|
||||||
}
|
|
||||||
events.emit("runtime-event",{id:"flows-run-state", payload: state, retain:true});
|
|
||||||
|
|
||||||
|
|
||||||
if (credentialsPendingReset === true) {
|
if (credentialsPendingReset === true) {
|
||||||
credentialsPendingReset = false;
|
credentialsPendingReset = false;
|
||||||
} else {
|
} else {
|
||||||
events.emit("runtime-event",{id:"runtime-state",retain:true});
|
events.emit("runtime-event",{id:"runtime-state", payload:{ state: 'start', deploy:isDeploy}, retain:true});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!muteLog && reallyStarted) {
|
if (!muteLog) {
|
||||||
if (type !== "full") {
|
if (type !== "full") {
|
||||||
log.info(log._("nodes.flows.started-modified-"+type));
|
log.info(log._("nodes.flows.started-modified-"+type));
|
||||||
} else {
|
} else {
|
||||||
@ -419,7 +419,7 @@ async function start(type,diff,muteLog) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stop(type,diff,muteLog) {
|
function stop(type,diff,muteLog,isDeploy) {
|
||||||
if (!started) {
|
if (!started) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
@ -439,6 +439,7 @@ function stop(type,diff,muteLog) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
started = false;
|
started = false;
|
||||||
|
state = 'stop'
|
||||||
var promises = [];
|
var promises = [];
|
||||||
var stopList;
|
var stopList;
|
||||||
var removedList = diff.removed;
|
var removedList = diff.removed;
|
||||||
@ -490,7 +491,8 @@ function stop(type,diff,muteLog) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
events.emit("flows:stopped",{config: activeConfig, type: type, diff: diff});
|
events.emit("flows:stopped",{config: activeConfig, type: type, diff: diff});
|
||||||
events.emit("runtime-event",{id:"flows-run-state", payload: {started: false, state: "stopped"}, retain:true});
|
|
||||||
|
events.emit("runtime-event",{ id:"runtime-state", payload:{ state: 'stop', deploy:isDeploy }, retain:true });
|
||||||
// Deprecated event
|
// Deprecated event
|
||||||
events.emit("nodes-stopped");
|
events.emit("nodes-stopped");
|
||||||
});
|
});
|
||||||
@ -810,7 +812,7 @@ module.exports = {
|
|||||||
stopFlows: stop,
|
stopFlows: stop,
|
||||||
|
|
||||||
get started() { return started },
|
get started() { return started },
|
||||||
|
state: () => { return state },
|
||||||
// handleError: handleError,
|
// handleError: handleError,
|
||||||
// handleStatus: handleStatus,
|
// handleStatus: handleStatus,
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ function start() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return redNodes.loadContextsPlugin().then(function () {
|
return redNodes.loadContextsPlugin().then(function () {
|
||||||
redNodes.loadFlows().then(redNodes.startFlows).catch(function(err) {});
|
redNodes.loadFlows().then(() => { redNodes.startFlows() }).catch(function(err) {});
|
||||||
started = true;
|
started = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -399,12 +399,12 @@ module.exports = {
|
|||||||
* @memberof @node-red/runtime
|
* @memberof @node-red/runtime
|
||||||
*/
|
*/
|
||||||
version: externalAPI.version,
|
version: externalAPI.version,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @memberof @node-red/diagnostics
|
* @memberof @node-red/diagnostics
|
||||||
*/
|
*/
|
||||||
diagnostics:externalAPI.diagnostics,
|
diagnostics:externalAPI.diagnostics,
|
||||||
|
|
||||||
storage: storage,
|
storage: storage,
|
||||||
events: events,
|
events: events,
|
||||||
hooks: hooks,
|
hooks: hooks,
|
||||||
|
@ -122,6 +122,7 @@
|
|||||||
"stopped-flows": "Stopped flows",
|
"stopped-flows": "Stopped flows",
|
||||||
"stopped": "Stopped",
|
"stopped": "Stopped",
|
||||||
"stopping-error": "Error stopping node: __message__",
|
"stopping-error": "Error stopping node: __message__",
|
||||||
|
"updated-flows": "Updated flows",
|
||||||
"added-flow": "Adding flow: __label__",
|
"added-flow": "Adding flow: __label__",
|
||||||
"updated-flow": "Updated flow: __label__",
|
"updated-flow": "Updated flow: __label__",
|
||||||
"removed-flow": "Removed flow: __label__",
|
"removed-flow": "Removed flow: __label__",
|
||||||
|
Loading…
Reference in New Issue
Block a user