Parse-server: Queries with Parse.Promise.when cause "Request timeout"

Created on 17 Feb 2016  路  15Comments  路  Source: parse-community/parse-server

There are a couple places in our app where we do things in parallel with Parse.Promise.when(), they worked in the Hosted Parse, but not anymore after migration. Is it supported?

Here's the general structure of those cloud functions:

var promises = [];

var query1 = new Parse.Query("Class1");
query1.equalTo("checked",false);
promises.push(query1.find());

var query2 = new Parse.Query("Class2");
query2.containedIn("name",["foo","bar"]);
promises.push(query2.find());

Parse.Promise.when(promises).then(function(results1,results2){
    // process results and return to client
}, function(error){
    // handle error
})

Server log when these functions are called:
at=error code=H12 desc="Request timeout" method=POST path="/parse/functions/myfunction" host=host request_id=123456 fwd="1.2.3.4" dyno=web.1 connect=1ms service=30001ms status=503 bytes=0

bug

Most helpful comment

Ahh... our hosted parse is using v1.6.14, which I think is why it's working there but not in parse-server. I think my issue is fixed. Thanks guys!

All 15 comments

I just changed all those calls so they do queries in series, which made them significantly slower, but at least they started working again.

Would still like to know if Parse.Promise.when() is bugged, or if it's supported at all.

Here's the call that works:

var results1, results2;

var query1 = new Parse.Query("Class1");
query1.equalTo("checked",false);
query1.find().then(function(results){
    results1 = results;

    var query2 = new Parse.Query("Class2");
    query2.containedIn("name",["foo","bar"]);
    return query2.find();
}).then(function(results){
    results2 = results;

    // process results and return to client
}, function(error){
    // handle error
})

I think I'm seeing the same thing. We have cloud code that is structured similar to the first example: create an array of promises and then wait for them all to complete before returning to the client.

I'm finding that while this cloud code ran fine on hosted parse, it times out in the open source version. Are promises a work in progress?

Promises are not a work in progress, this sounds like a real bug. We'll see if we can track this down. If you would like to help, you could submit a PR that includes a failing test case, or check the source to see if you can narrow down where the issue might be.

Does this bug exist in all version of Pars-server ? Or just in 2.0.1 up?

@refre5h @derekvanvliet Please see the PR that I just opened, in spec/issue456.spec.js that tries to reproduce the bug.
Unfortunately I can't...

This could be timing out if they are querying large amounts of data, as we no longer enforce query size limits like we did in Parse Server. @refre5h @derekvanvliet do you still have the problem if you add a limit to your query?

@flovilmart @drew-gross The timeout happens when the query1.find() and query2.find() are pushed to an array which is then passed in Parse.Promise.when(), like below. This method can be found in the Parse JS Promises in Parallel guide.

var promises = [];

var query1 = new Parse.Query("Foo");
promises.push(query1.find());

var query2 = new Parse.Query("Bar");
promises.push(query2.find());

Parse.Promise.when(promises).then()

However, it does not time out if it's structured like this:

var query1 = new Parse.Query("Foo");
var query2 = new Parse.Query("Bar");
Parse.Promise.when(query1.find(),query2.find())

I have just tested these in our server (Heroku + MongoLab, both free tier) against 2 tables that each have less than 20 entries, the one with the promises array timed out, but the one without didn't. I doubt it's because of the data size, it's very likely an issue related with the promises array.

@refre5h See the latest version of the test I'm running, and in particular: "testCreateManyObjectInParallel"
I create 200 ObjectA, and 200 ObjectB, push the promises with a Parse.Object.saveAll()

Then I fetch all of those objects, (the 400) with 2 queries built the way you describe. And it's still working correctly.

@drew-gross all of my queries (except for config.get) use limits and I was still having the problem. The problem went away for me when I added the rejected callbacks to the promise (as described in PR https://github.com/ParsePlatform/parse-server/pull/479)

So the timeout was likely to be because you were not handling errors?

@refre5h I think we have traced @derekvanvliet to a missing environment variable (the one that enables experimental config in Parse Server). Also, do any the promises in the array you pass to when fail? If they do, what is the error?

@drew-gross No error, just times out. I don't think the promises in the array have failed. But I found some interesting stuffs. Read on.

@flovilmart You are right, I ran the exact testCreateManyObjectInParallel call in our environment and it worked correctly without error or timeout. So I compared it with our original functions and discovered this one difference:

In your code, the .then(function(res){}) in Parse.Promise.when(promises).then(function(res){}) only has one argument res. However, our functions have multiple arguments like so: Parse.Promise.when(promises).then(function(res1,res2,res3){}). The number of arguments we put in there is the same as the number of queries in the promises.

I then proceed to only put one res, and get all the items in res as res[0], res[1], res[2], and it's not timing out anymore.

I also tried removing the promise array and pass all queries individually to .when(q1.find(),q2.find(),q3.find()), and 3 arguments in .then(function(res1,res2,res3){}), this also does not time out.

// THIS TIMES OUT
Parse.Promise.when(promises).then(function(res1,res2,res3){
    // process res1, res2, res3
}, function(e){
    // handle error
})

// THIS DOES NOT TIME OUT
Parse.Promise.when(promises).then(function(res){
    // process res[0], res[1], res[2]
}, function(e){
    // handle error
})

// THIS DOES NOT TIME OUT
Parse.Promise.when(query1.find(), query2.find(), query3.find())
             .then(function(res1, res2, res3){
    // process res1, res2, res3
}, function(e){
    // handle error
})

It looks like @andrewimm changed the behaviour of Parse.Promise.when in JavaScript SDK version 1.7.0, in a way that is related to your issue. https://github.com/ParsePlatform/Parse-SDK-JS/releases/tag/v1.7.0 can you check what version of the JavaScript SDK you are using?

@refre5h this is in the documentation of Parse.Promise in order to keep the consistency in the results depending how you passed you multiple promisses, as array or list of arguments.

http://www.parse.com/docs/js/api/classes/Parse.Promise.html#methods_when

:)

Ahh... our hosted parse is using v1.6.14, which I think is why it's working there but not in parse-server. I think my issue is fixed. Thanks guys!

Was this page helpful?
0 / 5 - 0 ratings