I am using node.js along with express. I have a REST API open which is
app.get('/pushtoqueue/:id', function(req, res){
//do something
callFunction(data, function(){
//Do sequential execution
});
}
When REST gets requests it calls callFunction, where this functions needs to be executed in sequential way. Which means, when REST gets called 1st time request should be processed, while callFunction is in execution if another request arrives for callFunction that should be queued until 1st execution is completed and so on for more future request.
How can I achieve this in node.js. Is there any way to queue requests?
You need to use a queue that autoexecutes their elements. If the queue is empty, when you push the first task then it is immediately executed. While the task is being executed another task might be pushed, so instead of being executed it is just enqueued.
I have a module that does exactly this: deferred-queue
Related
Console log Image
const express = require('express');
const app = express();
const port = 4444;
app.get('/', async (req, res) => {
console.log('got request');
await new Promise(resolve => setTimeout(resolve, 10000));
console.log('done');
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
If I hit get request http://localhost:4444 three times concurrently then it is returning logs as below
got request
done
got request
done
got request
done
Shouldn't it return the output in the below way because of nodes event loop and callback queues which are external to the process thread? (Maybe I am wrong, but need some understanding on Nodes internals) and external apis in node please find the attached image
Javascript Run time environment
got request
got request
got request
done
done
done
Thanks to https://stackoverflow.com/users/5330340/phani-kumar
I got the reason why it is blocking. I was testing this in chrome. I am making get requests from chrome browser and when I tried the same in firefox it is working as expected.
Reason is because of this
Chrome locks the cache and waits to see the result of one request before requesting the same resource again.
Chrome stalls when making multiple requests to same resource?
It is returning the response like this:
Node.js is event driven language. To understand the concurrency, you should look a How node is executing this code. Node is a single thread language(but internally it uses multi-thread) which accepts the request as they come. In this case, Node accepts the request and assign a callback for the promise, however, in the meantime while it is waiting for the eventloop to execute the callback, it will accept as many request as it can handle(ex memory, cpu etc.). As there is setTimeout queue in the eventloop all these callback will be register there and once the timer is completed the eventloop will exhaust its queue.
Single Threaded Event Loop Model Processing Steps:
Client Send request to the Node.js Server.
Node.js internally maintains a limited(configurable) Thread pool to provide services to the Client Requests.
Node.js receives those requests and places them into a Queue that is known as “Event Queue”.
Node.js internally has a Component, known as “Event Loop”. Why it got this name is that it uses indefinite loop to receive requests and process them.
Event Loop uses Single Thread only. It is main heart of Node JS Platform Processing Model.
Event Loop checks any Client Request is placed in Event Queue. If not then wait for incoming requests for indefinitely.
If yes, then pick up one Client Request from Event Queue
Starts process that Client Request
If that Client Request Does Not requires any Blocking IO Operations, then process everything, prepare response and send it back to client.
If that Client Request requires some Blocking IO Operations like interacting with Database, File System, External Services then it will follow different approach
Checks Threads availability from Internal Thread Pool
Picks up one Thread and assign this Client Request to that thread.
That Thread is responsible for taking that request, process it, perform Blocking IO operations, prepare response and send it back to the Event Loop
You can check here for more details (very well explained).
Environment: Node.js, Express
Question: When the end of a route is hit does all asynchronous code that has not yet completed stop? I have been experimenting for several hours and this seems to be true but is there a definitive answer?
Example: In the simplified example below when the / route is hit getInfoAndSaveIt is called. This function has a fetch call that will be slow followed by a database save that will also be slow. In the route the program will certainly reach the line res.render('homepage'); before the function has completed. In this case does homepage render and all async code in the function that has not yet completed stop? Or alternately does the async code continue in the background even though the end of the route has been hit?
app.get('/', function(req, res) {
getInfoAndSaveIt();
res.render('homepage');
});
function getInfoAndSaveIt() {
let randomData = fetch('https://www.example.com/data.txt');
User.updateOne({ data: randomData }, { id: 'abc123' });
}
With Node.js, Express when the end of a route is hit does all asynchronous code that has not yet completed stop?
No. Asynchronous code has a mind of its own and has no direct connection to a particular route. For example, imagine you were using some asynchronous code to do some logging. You send the response and then you call some asynchronous code to log some data. That logging will continue on just fine. It has no direct connection to the route. It's just Javascript running in the interpreter.
As for your example:
In this case does homepage render and all async code in the function that has not yet completed stop?
Yes, the homepage will render. Your async code will finish on its own.
Or alternately does the async code continue in the background even though the end of the route has been hit?
Yes, the async code continues on its own.
Try this simple example:
app.get('/', function(req, res) {
setTimeout(() => {
console.log("timer fired");
}, 2000);
res.render('homepage');
console.log("done rendering page");
});
When you hit this route, you will see this in the server logs:
done rendering page
timer fired
As evidence that an asynchronous operation continues after the route is done.
Keep in mind that processing a route in node.js is just another asynchronous operation. It's not some magic process thing or thread thing. It's just an asynchronous operation triggered by the incoming http request. So, there's no magic properties that would go find all asynchronous operations started by this and kill them somehow. That's not how node.js works. It's the opposite. Once you start them, they have a mind of their own and will complete regardless of what else is doing on in the process unless the process crashes or you specifically call process.exit().
I have this file named index.js:
const express = require('express')
const app = express()
const port = 3000
app.get('/home', (req, res) => {
res.send('Hello World!')
})
app.get('/route1', (req, res) => {
var num = 0;
for(var i=0; i<1000000; i++) {
num = num+1;
console.log(num);
}
res.send('This is Route1 '+ num)
})
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
I first call the endpoint /route1 and then immediately the endpoint /home. The /route1 has for loop and takes some time to finish and then /home runs and finishes. My question is while app was busy processing /route1, how was the request to /home handled, given node js is single threaded?
The incoming request will be queued in the nodejs event queue until nodejs gets a chance to process the next event (when your long running event handler is done).
Since nodejs is an event-driven system, it gets an event from the event queue, runs that event's callback until completion, then gets the next event, runs it to completion and so on. The internals of nodejs add things that are waiting to be run to the event queue so they are queued up ready for the next cycle of the event loop.
Depending upon the internals of how nodejs does networking, the incoming request might be queued in the OS for a bit and then later moved to the event queue until nodejs gets a chance to serve that event.
My question is while app was busy processing /route1, how was the request to /home handled, given node js is single threaded?
Keep in mind that node.js runs your Javascript as single threaded (though we do now have Worker Threads if you want), but it does use threads internally to manage things like file I/O and some other types of asynchronous operations. It does not need threads for networking, though. That is managed with actual asynchronous interfaces from the OS.
Nodejs has event loop and event loop allows nodejs to perform non blocking I/O operation. Each event loop iteration is called a tick. There are different phases of the event loop.
First is timer phase, since there are no timers in your script event loop will go further to check I/O script.
When you hit route /route1, Node JS Web Server internally maintains a Limited Thread pool to provide services to the Client Requests. It will be placed in FIFO queue then event loop will go further to polling phase.
Polling phase will wait for pending I/O, which is route /route1. Even Loop checks any Client Request is placed in Event Queue. If no, then wait for incoming requests for indefinitely.
Meanwhile next I/O script arrives in FIFO queue which is route /home.
FIFO means, first in first out. Therefore first /route1 will get execute the route /home
Below you can see this via diagram.
A Node.js application runs on single thread and the event loop also runs on the same thread
Node.js internally uses the libuv library which is responsible for handling operating system related tasks, like asynchronous I/O based operation systems, networking, concurrency.
More info
Node has an internal thread pool from which a thread is assigned when a blocking(io or memeory or network) request is sent. If not, then the request is processed and sent back as such. If the thread pool is full, the request waits in the queue. Refer How, in general, does Node.js handle 10,000 concurrent requests? for more clear answers.
I'd like to know how does NodeJS process multiple GET requests from different users/browsers which have event emitted to return the results? I'd like to think of it as each time a user executes the GET request, it's as if a new session is started for that user.
For example if I have this GET request
var tester = require('./tester-class');
app.get('/triggerEv', async function(req, res, next) {
// Start the data processing
tester.startProcessing('some-data');
// tester has event emitters that are triggered when processing is complete (success or fail)
tester.on('success', function(data) {
return res.send('success');
}
tester.on('fail', function(data) {
return res.send('fail');
}
}
What I'm thinking is that if I open a browser and run this GET request by passing some-data and start processing. Then open another browser to execute this GET request with different data (to simulate multiple users accessing it at the same time), it will overwrite the previous startProcessing function and rerun it again with the new data.
So if multiple users execute this GET request at the same time, would it handle it separately for each user as if it was different and independent sessions then return when there's a response for each user's sessions? Or will it do as I mentioned above (this case I will have to somehow manage different sessions for each user that triggers this GET request)?
I want to make it so that each user that executes this GET request doesn't interfere with other users that also execute this GET request at the same time and the correct response is returned for each user based on their own data sent to the startProcessing function.
Thanks, I hope I'm making sense. Will clarify if not.
If you're sharing the global tester object among different requests, then the 2nd request will interfere with the first request. Since all incoming requests use the same global environment in node.js, the usual model is that any request that may be "in-flight" for awhile needs to create its own resources and keep them for itself. Then, if some other request arrives while the first one is still waiting for something to complete, then it will also create its own resources and the two will not conflict.
The server environment does not have a concept of "sessions" in the way you're using the term. There is no separate server-session or server state that each request lives in other than the request and response objects that are created for each incoming request. This is not like PHP - there is not a whole new interpreter state for each request.
I want to make it so that each user that executes this GET request doesn't interfere with other users that also execute this GET request at the same time and the correct response is returned for each user based on their own data sent to the startProcessing function.
Then, don't share any resources between requests and don't use any objects that have global state. I don't know what your tester is, but one way to keep multiple requests separate from each other is to just make a new tester object for each request so they can each use it to their heart's content without any conflict.
I am looking into using newrelic APM to monitor certain parts of our codebase.
I want to watch transactions that are not simple HTTP calls, but background processes. These transactions are completed by worker processes and we want to monitor them in the main part of the app.
Pseudo code:
var fork = childProcess.spawn('node', ['--harmony', 'path-to-worker.js', args]);
fork.stdout.on('data', function(data) {
// a finished transaction
// this fires most likely more than once
});
We basically need something like newrelic.createBackgroundTransaction() that can log a transaction immediately, without having to pass it a function to execute and time (I can do that myself).
Can I do something like this on the free tier of newrelic?