'Fire and forget' promises in a serverless (NextJS) environment - node.js

I'm adding third party logging to my nodejs app, the API has an ingestion endpoint I need to call with logging information.
The problem is that this request takes time, if I await all the logging requests it will add significant time to function executions.
My thinking was to do a 'fire and forget' approach however given NextJS will cancel all executing processes this may occasionally fail. I also found logging may arrive in a different order than sent (though this can be mediated with a timestamp).
What I'd love to do is fire off the log and ensure the request has been sent without waiting on the response from the server - is this possible?
I'm thinking to add a 1ms wait after each log since an initial http request with a small payload isn't going to take that long to send but wanted to know are their any best practices for handling these sorts of scenarios?

Related

Sending a response after jobs have finished processing in Express

So, I have Express server that accepts a request. The request is web scraping that takes 3-4 minute to finish. I'm using Bull to queue the jobs and processing it as and when it is ready. The challenge is to send this results from processed jobs back as response. Is there any way I can achieve this? I'm running the app on heroku, but heroku has a request timeout of 30sec.
You don’t have to wait until the back end finished do the request identified who is requesting . Authenticate the user. Do a res.status(202).send({message:”text});
Even though the response was sended to the client you can keep processing and stuff
NOTE: Do not put a return keyword before res.status...
The HyperText Transfer Protocol (HTTP) 202 Accepted response status code indicates that the request has been accepted for processing, but the processing has not been completed; in fact, processing may not have started yet. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place.
202 is non-committal, meaning that there is no way for the HTTP to later send an asynchronous response indicating the outcome of processing the request. It is intended for cases where another process or server handles the request, or for batch processing.
You always need to send response immediately due to timeout. Since your process takes about 3-4 minutes, it is better to send a response immediately mentioning that the request was successfully received and will be processed.
Now, when the task is completed, you can use socket.io or web sockets to notify the client from the server side. You can also pass a response.
The client side also can check continuously if the job was completed on the server side, this is called polling and is required with older browsers which don't support web sockets. socket.io falls back to polling when browsers don't support web sockets.
Visit socket.io for more information and documentation.
Best approach to this problem is socket.io library. It can send data to client send whenever you want. It triggers a function on client side which receives the data. Socket.io supports different languages and it is really ease to use.
website link
Documentation Link
create a jobs table in a database or persistant storage like redis
save each job in the table upon request with a unique id
update status to running on starting the job
sent HTTP 202 - Accepted
At the client implement a polling script, At the server implement a job status route/api. The api accept a job id and queries the job table and respond with the status
When the job is finished update the job table with status completed, when the jon is errored updated the job table with status failed and maybe a description column to store the cause for error
This solution makes your system horizontaly scalable and distributed. It also prevents the consequences of unexpected connection drops. Polling interval depends on average job completion duration. I would recommend an average interval of 5 second
This can be even improved to store job completion progress in the jobs table so that the client can even display a progress bar
->Request time out occurs when your connection is idle, different servers implement in a different way so timeout time differs
1)The solution for this timeout problem would be to make your connections open(constant), that is the connection between client and servers should remain constant.
So for such scenarios use WebSockets, which ensures that after the initial request and response handshake between client and server the connection stays open.
there are many libraries to implement realtime connection.Eg Pubnub,socket.io. This is the same technology used for live streaming.
Node js can handle many concurrent connections and its lightweight too, won't use many resources too.

One API call vs multiple

I have a process in the back-end which will take take on average 30 to 90 seconds to complete.
Is it better to have a font-end react app make ONE API call and wait for back-end to complete and process and return the data. Or is it better to have the front-end make multiple calls, lets say every 2 seconds to check if the process and complete and get back the result?
Both are valid approaches. You could also report status changes with websocket so there's no need for polling.
If you do want to go the polling route, the general recommendation is to:
Return 202 accepted from your long-running process endpoint.
Also return a Link header with a url to where the status of the process can be read.
The client can then follow that client and ping it every x seconds.
I think it's not good to make a single API call and wait for 30-90 seconds to get a response. Instead send a response immediately mentioning that the request is successful and would be processed.
Now you can use web sockets or library like socket.io so that the server can communicate directly to the client once the requested processing is complete.
The multiple API calls to check if server is done or server has any new message is called polling and is not much efficient but it is still required in old browsers which don't support web sockets. Socket.io support s polling automatically in old browsers.
But, yes if you want you can do multiple calls to check if server is done processing, but I would prefer server to communicate back to the client , it is better.

Manage responses of hastily aborted requests

My problem is this:
I have a React Native app that requests data to the backend.
If backend takes longer than x seconds, the app aborts the request (made with fetch()) and tries to make another one.
That abortion was hastily, because the backend was just taking a longer time to process it.
The backend is made idempotent so new requests don't actually matter.
The backend finished processing the initial request, and now it wants to return the value, but that request was aborted by the client.
How should I deal with this?
I can't just abandon the abortion logic because it's not my app, but I can make simple fixes and improve logic on it. Also, I can do whatever it takes in the backend.
I've solved it by saving the express.Response objects alongside it's requests. Whenever a new, duplicate, request arrives I just replace the response object in an array, so that I always have a way to respond the app.

Best practice to respond restfully to a time consuming calculation (Node.js with Express)

Best way to respond restfully to a time consuming calculation (Node.js with Express)
I'm building a REST API using Node.js with Express.
Now I have to design the response to a time consuming calculation on the server side to a http request witch is ending up in a zip file with a few megabytes.
The calculation is done in a few seconds at the moment. But perhaps, if data grows up, it can take minutes sometime. So I think it's not the best way to wait in Express till data is ready and then res.sendfile() it back to the client. But what is the best solution?
Should I implement a delayed response with long polling? Like http-delayed-response
What I don't like here is that I immediately have to report HTTP 202. If the generation of the ZIP file fails, I have to deal with this in the response and cannot report it via HTTP status code. Also I cannot respond the file directly - as far as I know.
Or something with job ids and states to each job? Like express-delayed-response
In this way my API is not stateless anymore and I have to build a status handler.
Are there better and more established solutions to this problem?

How to configure maximum concurrency of Node.js HTTP server?

I want to restrict HTTP server to processing at most 1 request at a time. The use case is to enable linear-inspection of the logs when troubleshooting.
In principle, I could implement the queueing logic in the requestListener. This would simply require to know when the last request has been handled.
However, I wonder if there is a lower-level approach, e.g. delaying the connection response.

Resources