mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge c1fbff1e1894ab27cc4daea98b47a9898f272275 into bb01f26f068b8e083e35fdf19dc9b36f8cf67068
This commit is contained in:
commit
3c3779582f
@ -399,6 +399,8 @@ module.exports = function(RED) {
|
|||||||
if(node.timeout>0){
|
if(node.timeout>0){
|
||||||
finOpt.timeout = node.timeout;
|
finOpt.timeout = node.timeout;
|
||||||
finOpt.breakOnSigint = true;
|
finOpt.breakOnSigint = true;
|
||||||
|
} else if(RED.settings.defaultFunctionTimeout > 0){
|
||||||
|
finOpt.timeout = RED.settings.defaultFunctionTimeout * 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var promise = Promise.resolve();
|
var promise = Promise.resolve();
|
||||||
@ -415,8 +417,15 @@ module.exports = function(RED) {
|
|||||||
var opts = {};
|
var opts = {};
|
||||||
if (node.timeout>0){
|
if (node.timeout>0){
|
||||||
opts = node.timeoutOptions;
|
opts = node.timeoutOptions;
|
||||||
|
} else if(RED.settings.defaultFunctionTimeout > 0){
|
||||||
|
opts.timeout = RED.settings.defaultFunctionTimeout * 1000
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
node.script.runInContext(context,opts);
|
||||||
|
} catch (err) {
|
||||||
|
node.error(err);
|
||||||
|
return done(err);
|
||||||
}
|
}
|
||||||
node.script.runInContext(context,opts);
|
|
||||||
context.results.then(function(results) {
|
context.results.then(function(results) {
|
||||||
sendResults(node,send,msg._msgid,results,false);
|
sendResults(node,send,msg._msgid,results,false);
|
||||||
if (handleNodeDoneCall) {
|
if (handleNodeDoneCall) {
|
||||||
|
23
packages/node_modules/node-red/settings.js
vendored
23
packages/node_modules/node-red/settings.js
vendored
@ -473,6 +473,7 @@ module.exports = {
|
|||||||
* - fileWorkingDirectory
|
* - fileWorkingDirectory
|
||||||
* - functionGlobalContext
|
* - functionGlobalContext
|
||||||
* - functionExternalModules
|
* - functionExternalModules
|
||||||
|
* - defaultFunctionTimeout
|
||||||
* - functionTimeout
|
* - functionTimeout
|
||||||
* - nodeMessageBufferMaxLength
|
* - nodeMessageBufferMaxLength
|
||||||
* - ui (for use with Node-RED Dashboard)
|
* - ui (for use with Node-RED Dashboard)
|
||||||
@ -499,6 +500,28 @@ module.exports = {
|
|||||||
/** Allow the Function node to load additional npm modules directly */
|
/** Allow the Function node to load additional npm modules directly */
|
||||||
functionExternalModules: true,
|
functionExternalModules: true,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default function timeout (in seconds) for the Function node.
|
||||||
|
* A value of 0 indicates no timeout is applied, meaning the function can run indefinitely.
|
||||||
|
*
|
||||||
|
* The default function timeout is designed to prevent blocking code in function nodes,
|
||||||
|
* which could otherwise lead to a stalled or unresponsive main thread. For example,
|
||||||
|
* the following code would block the event loop indefinitely:
|
||||||
|
*
|
||||||
|
* `while(1) {}`
|
||||||
|
*
|
||||||
|
* By specifying a `defaultFunctionTimeout`, such scenarios can be mitigated,
|
||||||
|
* ensuring that long-running or infinite loops are terminated automatically after
|
||||||
|
* the specified timeout duration.
|
||||||
|
*
|
||||||
|
* Note: If both `defaultFunctionTimeout` and `functionTimeout` are defined in the
|
||||||
|
* settings file, `functionTimeout` takes precedence, providing a more granular
|
||||||
|
* control for individual function nodes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
defaultFunctionTimeout: 0,
|
||||||
|
|
||||||
/** Default timeout, in seconds, for the Function node. 0 means no timeout is applied */
|
/** Default timeout, in seconds, for the Function node. 0 means no timeout is applied */
|
||||||
functionTimeout: 0,
|
functionTimeout: 0,
|
||||||
|
|
||||||
|
@ -1437,7 +1437,7 @@ describe('function node', function() {
|
|||||||
var logEvents = helper.log().args.filter(function(evt) {
|
var logEvents = helper.log().args.filter(function(evt) {
|
||||||
return evt[0].type == "function";
|
return evt[0].type == "function";
|
||||||
});
|
});
|
||||||
logEvents.should.have.length(1);
|
logEvents.should.have.length(2);
|
||||||
var msg = logEvents[0][0];
|
var msg = logEvents[0][0];
|
||||||
msg.should.have.property('level', helper.log().ERROR);
|
msg.should.have.property('level', helper.log().ERROR);
|
||||||
msg.should.have.property('id', 'n1');
|
msg.should.have.property('id', 'n1');
|
||||||
@ -1451,7 +1451,7 @@ describe('function node', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('check if default function timeout settings are recognized', function (done) {
|
it('check if function timeout settings are recognized', function (done) {
|
||||||
RED.settings.functionTimeout = 0.01;
|
RED.settings.functionTimeout = 0.01;
|
||||||
var flow = [{id: "n1",type: "function",timeout: RED.settings.functionTimeout,wires: [["n2"]],func: "while(1==1){};\nreturn msg;"}];
|
var flow = [{id: "n1",type: "function",timeout: RED.settings.functionTimeout,wires: [["n2"]],func: "while(1==1){};\nreturn msg;"}];
|
||||||
helper.load(functionNode, flow, function () {
|
helper.load(functionNode, flow, function () {
|
||||||
@ -1463,7 +1463,7 @@ describe('function node', function() {
|
|||||||
var logEvents = helper.log().args.filter(function (evt) {
|
var logEvents = helper.log().args.filter(function (evt) {
|
||||||
return evt[0].type == "function";
|
return evt[0].type == "function";
|
||||||
});
|
});
|
||||||
logEvents.should.have.length(1);
|
logEvents.should.have.length(2);
|
||||||
var msg = logEvents[0][0];
|
var msg = logEvents[0][0];
|
||||||
msg.should.have.property('level', helper.log().ERROR);
|
msg.should.have.property('level', helper.log().ERROR);
|
||||||
msg.should.have.property('id', 'n1');
|
msg.should.have.property('id', 'n1');
|
||||||
@ -1479,6 +1479,65 @@ describe('function node', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('check if default function timeout settings are recognized', function (done) {
|
||||||
|
RED.settings.defaultFunctionTimeout = 0.01;
|
||||||
|
var flow = [{id: "n1",type: "function",wires: [["n2"]],func: "while(1==1){};\nreturn msg;"}];
|
||||||
|
helper.load(functionNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
n1.receive({ payload: "foo", topic: "bar" });
|
||||||
|
setTimeout(function () {
|
||||||
|
try {
|
||||||
|
helper.log().called.should.be.true();
|
||||||
|
var logEvents = helper.log().args.filter(function (evt) {
|
||||||
|
return evt[0].type == "function";
|
||||||
|
});
|
||||||
|
logEvents.should.have.length(2);
|
||||||
|
var msg = logEvents[0][0];
|
||||||
|
msg.should.have.property('level', helper.log().ERROR);
|
||||||
|
msg.should.have.property('id', 'n1');
|
||||||
|
msg.should.have.property('type', 'function');
|
||||||
|
should.equal(RED.settings.defaultFunctionTimeout, 0.01);
|
||||||
|
should.equal(msg.msg.message, 'Script execution timed out after 10ms');
|
||||||
|
delete RED.settings.defaultFunctionTimeout;
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('check if functionTimeout has higher precedence over default function timeout setting', function (done) {
|
||||||
|
RED.settings.defaultFunctionTimeout = 0.02;
|
||||||
|
RED.settings.functionTimeout = 0.01;
|
||||||
|
var flow = [{id: "n1",type: "function",timeout: RED.settings.functionTimeout,wires: [["n2"]],func: "while(1==1){};\nreturn msg;"}];
|
||||||
|
helper.load(functionNode, flow, function () {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
n1.receive({ payload: "foo", topic: "bar" });
|
||||||
|
setTimeout(function () {
|
||||||
|
try {
|
||||||
|
helper.log().called.should.be.true();
|
||||||
|
var logEvents = helper.log().args.filter(function (evt) {
|
||||||
|
return evt[0].type == "function";
|
||||||
|
});
|
||||||
|
logEvents.should.have.length(2);
|
||||||
|
var msg = logEvents[0][0];
|
||||||
|
msg.should.have.property('level', helper.log().ERROR);
|
||||||
|
msg.should.have.property('id', 'n1');
|
||||||
|
msg.should.have.property('type', 'function');
|
||||||
|
should.equal(RED.settings.functionTimeout, 0.01);
|
||||||
|
should.equal(RED.settings.defaultFunctionTimeout, 0.02);
|
||||||
|
should.equal(msg.msg.message, 'Script execution timed out after 10ms');
|
||||||
|
delete RED.settings.functionTimeout;
|
||||||
|
delete RED.settings.defaultFunctionTimeout;
|
||||||
|
done();
|
||||||
|
} catch (err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("finalize function", function() {
|
describe("finalize function", function() {
|
||||||
|
|
||||||
it('should execute', function(done) {
|
it('should execute', function(done) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user