I'm building a site and one particular operation triggers a long, server-side process to run. This operation can't be run twice at the same time, so I need to implement some sort of protection. It also can't be made synchronous, because the server needs to continue responding to other requests while it runs.
To that end I've constructed this small concept test, using sleep 5
as a substitute for my actual long-running process (requires express and child-process-promise, runs on a system with a sleep
command but substitute whatever for Windows):
var site = require("express")();
var exec = require("child-process-promise").exec;
var busy = false;
site.get("/test", function (req, res) {
if (busy) {
res.json({status:"busy"});
} else {
busy = true; // <-- set busy before we start
exec("sleep 5").then(function () {
res.json({status:"ok"});
}).catch(function (err) {
res.json({status:err.message});
}).then(function () {
busy = false; // <-- finally: clear busy
});
}
});
site.listen(8082);
The intention of this is when "/test" is requested it triggers a long operation, and if "/test" is requested again while it is running, it replies with "busy" and does nothing.
My question is, is this implementation safe and correct? It appears to work in my cursory tests but it's suspiciously simple. Is this the proper way to essentially implement a mutex + a "try-lock" operation, or is there some more appropriate Node.js construct? Coming from languages where I'm used to standard multithreading practices, I'm not quite comfortable with Node's single-threaded-but-asynchronous nature yet.
You're fine - Javascript code can't run concurrently with other JS code in Node. Nothing will change the busy flag out from under you. No need for multithreaded-styled monitors or critical sections.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With