I have a problem with my expressJS framework when I am sending a response with delay 200 seconds it's sending err_empty_response with status code 324
here is fakeTimer example
fakeTimeout(req, res) {
setTimeout(() => { res.json({success: true})}, 200000)
}
ERR_EMPTY_RESPONSE is a Google Chrome error code.
Actually, Chrome will automatically timeout requests when they exceeds 300 seconds, and there is no way to change that settings unfortunately.
One workaround could be to change the Keep Alive headers.
However, if one task is taking longer than one minute, you should really just don't let the user wait that amount of time and have a feedback later on the UI when it's completed.
Related
I'm looking to delay all requests to an endpoint 30 minutes from when it was originally received. I'm working with Shopify and am responding to an order creation webhook, passing along data to another 3rd party service.
This is what happens: an order is placed, and then a webhook fires via Shopify, which contacts my koa endpoint with the associated order data.
I want to receive the webhook body (which includes order data) immediately, but then wait 30 minutes, then send along that information to another service. But I want to send a 200 header back to Shopify immediately, regardless of whether or not the code executes properly after the 30 minute delay (if it doesn't, I'll be informed via an error email anyway and can handle it manually, it wouldn't be the end of the world).
I've tried setTimeout methods, but the issue seems to be this: I can't send a 200 header back to Shopify until after the 30 minutes is up (or I shouldn't anyway, according to Koa docs?).
Meaning, if I do something like
context.response.status = 200; // tried to send response code immediately due to 30 minute timeout.
await handleRequest(context.request.body); // code waits 30 mins via settimeout
the 200 header isn't being sent right away
By the time 30 minutes has passed, Shopify has long given up on receiving a 200 header and has automatically put the request in a retry queue, which means the webhook will fire again before the 30 minutes is up, so I'll be sending duplicate requests to the service I'm trying to wait 30 minutes for.
I've considered cron, but it's not that I want these to be processed every 30 minutes, I want each individual request to wait 30 minutes to send to a third party service after it was received.
I'm really trying to avoid a database.
I'm fine with using setTimeout, if there is a way to send a 200 header back to Shopify before the timeout and subsequent service call after 30 minutes.
Status code goes with the first part of the HTTP message, so you need to start sending, or end the HTTP response.
In this case, you don't need to block the response on the 3rd party call. Move the logic you want to run in 30 minutes into its own function and don't await on the timer. You don't need it in your response logic.
Some pseudo code:
function talkTo3rdPartyDelayed(context, delay) {
setTimeout(()=>{
// talk to 3rdparty
}, delay);
return; // continue what you were doing before, this is non-blocking
}
function listenForShopify(req, res, next) {
talkTo3rdPartyDelayed({req.body}, 30*60*1000);
res.statusCode = 200;
next(); // or res.end() which sends the status code
}
As an aside, in a robust system, you'd store that 3rd party request you want delayed for 30 minutes in a queue system, with a visibility timer set to 30 minutes ahead. That way, if the process dies, you don't lose that work you intended to do. Having to manually handle any issues that come up will get tiresome.
I am developing an app for google assistant on DialogFlow.
On certain intent I have a fullfilment which has to do a http request.
The code is like this:
const syncrequest = require('sync-request');
console.log('Request start');
var res = syncrequest('GET', urlRequest, {
json: {},
});
console.log('Request end');
Testing the url that I'm using it takes approximately 0.103 seconds to respond.
But looking at the firebase log, it is like this:
3:01:58.555 PM dialogflowFirebaseFulfillment Request end
3:01:56.585 PM dialogflowFirebaseFulfillment Request start
Even thought my server respond in 0.103 seconds, the request takes 2 seconds to be processed.
Sometimes it takes more than 4 seconds and makes my app crash.
Does anyone have any idea why is it taking so long? Is there something that I can do to do the request faster?
Thanks in advance
I haven't looked too hard at the sync-request package, but I do see this big warning on the npm page for it:
You should not be using this in a production application. In a node.js
application you will find that you are completely unable to scale your
server. In a client application you will find that sync-request causes
the app to hang/freeze. Synchronous web requests are the number one
cause of browser crashes. For production apps, you should use
then-request, which is exactly the same except that it is
asynchronous.
Based on this, and some other information on the page, it sounds like this package is very poor on performance, and may handle the synchronous operations grossly inefficiently.
You may wish to switch to the then-request package, as it suggests, however the most common way to handle HTTP calls is using request-promise-native, where you'd do something like:
const rp = require('request-promise-native');
return rp.get(url)
.then( body => {
// Set the Dialogflow response here
// You didn't really show this in your code.
});
If you are doing asynchronous tasks - you must return a promise from your intent handler.
I have implemented one heavy API using HapiJS a module of NodeJS. This API takes around 4-5 minutes for response. But in this case the client is showing 'Request Timeout' message. I want to send the progress to the client as keep-alive. Any help will be appreciated.
timeout.server is what you need. It sets the maximum time allowed for the server to respond to an incoming client request. You can set the time accordingly and meanwhile show a progress bar in the front end to the client.
server.route({
...
timeout: {
server: 4500
}
...
});
My request look this -
$http.post('/api/internal/Properties/' + options.property.id + '/Upload', { Buildings: Buildings })
.success(function (data){
on the server side, this request can take a long time to process. Up to 5 minutes. Before it can finish (res.send()), the $http.post request is being called again, every few minutes.
When it finally does finish processing, the res.send(data) is never caught on the client side. It's like it just disappears.
Anything would help.
Thanks,
Each browser has it's own http request timeout.
So it will not wait for 5 minutes to complete request it would just fail.
Browser Timeouts .
In chrome it's 30 or 60 seconds.
In your case i suggest use sockets or something like that to show user what's up with uploading.
Hope this helps.
I have app hosted on heroku + heroku postgres instance.
My REST api fetches some data from DATABASE and returns data back to client.
I am using Sequelize.js as ORM and restify.js as server.
My API function looks like this:
app.get('/test', function(req,res,next){
t1 = new Date()
db.getSomeData.done(function(err,result){
t2 = new Date()
console.log((t2.getTime()-t1.getTime())+'ms')
res.json({}) // it is not mistake, I return empty json to make sure that amount of data transfered back to client is not causing dely
next()
})
})
For tests I always fetch exactly same data from DB. console.log says that DB query takes 400-500ms. However when I am testing ajax requests (in chrome) and I can see that average request time is 500-800ms, but from time to time (it happens around 2-3 times per 10 tries) response is received after 3-5 seconds. This is strange because db query time is still normal (400ms for example) and I am not sending any data back to client. API is used only by me so there is no load on heroku server. I though that it might be caused by my internet connection so I made second test with following handler:
app.get('/test', function(req,res,next){
res.json({}) // it is not mistake, I return empty json to make sure that amount of data transfered back to client is not causing dely
next()
})
And for 100 times ther eis no delay - all requeststs are completed in 73-89 ms.
Do you know what might be a problem? It seems that request sometimes takes more time just because db query was done, no matter how much data is sent back. (despite that db query itself does not take time longer than normal)...
That is super-strange because I tried something like this:
app.get('/test', function(req,res,next){
setTimeout(function(){
res.json({}) // it is not mistake, I return empty json to make sure that amount of data transfered back to client is not causing dely
next()
},500)
})
And problem still occurs: 3-4 time per 10 tries response is received after 1.5 - 3.5 seconds where average is 800-900ms.
Also Response-Time header set by restify is correct despite the delay. For example:
Chrome says: 3.5s
Response-Time: 600s
It means that lag is caused by Heroku?
Resolved. It was a Heroku platform issue.
https://status.heroku.com/incidents/649
Investigating
Our automated systems have detected potential platform errors.
We are investigating.
Posted Jul 12, 2014 23:38 UTC