none
[Node.js][Mobile Service] Issues with timeouts when calling MobileService CustomAPI.. "fails to return from an asynchronous call in a timely manner." RRS feed

  • Question

  • Hello,

    I have been experiencing issues with one of my custom APIs and I was hoping somebody would be able to offer some assistance.
    The Application Log message I am getting is 

    {"timeCreated":"2016-03-01T13:30:23.296Z","type":"error","source":"","message":"The request 'POST /api/CalculateUserPoints' has timed out. This could be caused by a script that fails to write to the response, or otherwise fails to return from an asynchronous call in a timely manner."}


    I am calling the API on a button click from my Android application. The button loops through an ArrayList and gets an Id field which is then sends to the API. The Custom API is meant to update the value in one of my tables. 

    API and Code executing below: 
    API

    exports.post = function (request, response) {
        var mssql = request.service.mssql;
        var id = request.body.userid;
        var leagueid = request.body.leagueid;

        var sql = "UPDATE FaulsMobileService.userTeam SET FaulsMobileService.userTeam.userPoints = (SELECT (SUM(FaulsMobileService.fantasyPlayers.rulePointIncrement) + " +
    "FaulsMobileService.userTeam.userPoints) AS pointsthisweek FROM FaulsMobileService.userTeam JOIN FaulsMobileService.fantasyPlayers ON FaulsMobileService.fantasyPlayers.leagueID " +
    "= FaulsMobileService.userTeam.leagueId AND FaulsMobileService.userTeam.leagueId IN (" + leagueid + ") WHERE  FaulsMobileService.fantasyPlayers.Id IN (FaulsMobileService.userTeam.player1," +
    "FaulsMobileService.userTeam.player2, " +
    "FaulsMobileService.userTeam.player3," +
    "FaulsMobileService.userTeam.player4," +
    "FaulsMobileService.userTeam.player5," +
    "FaulsMobileService.userTeam.player6," +
    "FaulsMobileService.userTeam.player7," +
    "FaulsMobileService.userTeam.player8," +
    "FaulsMobileService.userTeam.player9," +
    "FaulsMobileService.userTeam.player10," +
    "FaulsMobileService.userTeam.player11) AND FaulsMobileService.userTeam.userId = " + id +
    "GROUP BY (FaulsMobileService.userTeam.userId), FaulsMobileService.userTeam.userPoints) " +
    "WHERE  FaulsMobileService.userTeam.userId = " + id;

        mssql.query(sql, {
            success: function (results) {
    if(results.length == 1)
                response.send(200, results);
            }
        });
    };


    Code:

       calcPointsButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    try {
                        for (int i = 0; i < ArrayList.size(); i++) {
                            final int finalI = i;
                            Thread t = new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        final JsonObject request = new JsonObject();
                                        request.addProperty("userid", Integer.parseInt(ArrayList.get(finalI).getUserId()));
                                        request.addProperty("leagueid", leagueId);
                                        mClient.invokeApi("CalculateUserPoints", request);

                                    } catch (Exception e) {
                                        e.getMessage();
                                    }
                                }
                            });
                            t.start(); // spawn thread
                            try {
                                t.join();  // wait for thread to finish
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            if (i == userInfoArrayList.size() - 1) {
                                calculateLeaguePositions(leagueId);
                               // resetPointChange();
                                Toast.makeText(getActivity().getApplicationContext(), "Points Calculated", Toast.LENGTH_SHORT).show();
                            }
                        }
                    } catch (Exception e) {
                        Toast.makeText(getActivity().getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
                    }
                };
            });
            return rootView;
        }



    Any assistance would be greatly appreciated,
    Kind Regards,
    CM





    Tuesday, March 1, 2016 1:33 PM

Answers

  • It seems your SQL stmt doesn't query the result as you expect, and there is not any error handle or handle for other result situation. So you get timeout exception.

    You can try to complete the code for mssql querying:

    mssql.query(sql, { 
            success: function (results) {
                if(results.length == 1)
                    response.send(200, results);
                }else{
                    console.log(result);
                    //some handle
                },
            error:function(err){
                console.log("error is: " + err);
            }
        });
    And monitor the Logs page in your mobile service portal for troubleshooting. 

     
    Wednesday, March 2, 2016 3:37 AM
    Moderator
  • Not all code paths return a response.  You should ensure all code paths always return a response - even if that is a failure.

    You should log the userid / leagueid and ensure you are getting the values you expect

    You should time the SQL statement to ensure it is returning in a small amount of time.

    Wednesday, March 2, 2016 10:14 PM

All replies

  • Anybody able to lend assistance on this matter?
    Or point me in another direction?

    Many Thanks,
    CM
    Tuesday, March 1, 2016 4:54 PM
  • Your bottleneck is most likely the database. You should add indexes on all of the columns you are doing a sort and filter on.

    Here's a stackoverflow post with some good tips: http://stackoverflow.com/questions/35650280/where-in-sql-command-optimization

    Here's an article on SQL optimization: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-sql-scale-guidance/

    Wednesday, March 2, 2016 1:50 AM
  • It seems your SQL stmt doesn't query the result as you expect, and there is not any error handle or handle for other result situation. So you get timeout exception.

    You can try to complete the code for mssql querying:

    mssql.query(sql, { 
            success: function (results) {
                if(results.length == 1)
                    response.send(200, results);
                }else{
                    console.log(result);
                    //some handle
                },
            error:function(err){
                console.log("error is: " + err);
            }
        });
    And monitor the Logs page in your mobile service portal for troubleshooting. 

     
    Wednesday, March 2, 2016 3:37 AM
    Moderator
  • Hello,

    Thank you for responses I shall investigate these ideas today,

    I am unsure whether or not it is the SQL Statement as when I run it manually (plugging in the Id fields in a query editor it seems to be ok). I shall add the logs still and take a look!

    Also looking into the indexing now. 
    Wednesday, March 2, 2016 10:44 AM
  • Sadly, Indexing has not seemed to solve the issue..

    I put an index on the players1 - 11 columns and UserID, Id and LeagueId
    Yet it still just updates the rows at random.
    No error message is being thrown either, just a time out..

    Any other possibilities?

    Thank you for the help! 
    Wednesday, March 2, 2016 11:07 AM
  • Not all code paths return a response.  You should ensure all code paths always return a response - even if that is a failure.

    You should log the userid / leagueid and ensure you are getting the values you expect

    You should time the SQL statement to ensure it is returning in a small amount of time.

    Wednesday, March 2, 2016 10:14 PM