1

I have a stored procedure which return 4000 documents, due to 5 sec execution limit my sproc is not retuning any data. I tried to handled collection accepted value but it is not working as expected.

I tried to set response to "return" in case of 5 sec limit hit, sproc is not setting response.

function getRequirementNodes() 
{
var context = getContext();
var response = context.getResponse();
var collection = context.getCollection();
var collectionLink = collection.getSelfLink();
var nodesBatch = [];
var continueToken= true;

var query = { query: 'SELECT * from root '};

getNodes(null)

function getNodes(continuation)
{
   var requestOptions = {continuation: continuation};
   var accepted = collection.queryDocuments(collectionLink, query,    requestOptions,
   function(err, documentsRead, responseOptions) 
   {
    if (documentsRead.length > 0)
    {
        nodesBatch = nodesBatch.concat(documentsRead);
    }
    else if (responseOptions.continuation)
    {
       continueToken = responseOptions.continuation
       nodesBatch = nodesBatch.concat(documentsRead);
       getNodes(responseOptions.continuation);
    }
        else 
        {
            continueToken= false;
            response.setBody(nodesBatch);
        }
        });

    if (!accepted) 
    { 
       response.setBody("return");
    } 
}
}

1 Answers1

6

The script is returning a empty response, because the blocks containing response.setBody() are never called.

I'll explain. Let's break this section of queryDocuments callback down:

if (documentsRead.length > 0) {
    nodesBatch = nodesBatch.concat(documentsRead);
} else if (responseOptions.continuation) {
    continueToken = responseOptions.continuation
    nodesBatch = nodesBatch.concat(documentsRead);
    getNodes(responseOptions.continuation);
} else {
    continueToken = false;
    response.setBody(nodesBatch);
}

Note that if the query has results inside the first page (which it most likely will)... The script will append the query results on to nodesBatch:

if (documentsRead.length > 0) {
    nodesBatch = nodesBatch.concat(documentsRead);
}

The script will then complete. The response body is unset (empty), and the script does not issue a follow up query if there is a continuation token.

Assuming the collection isn't empty, then this probably the behavior you are experiencing.


Note: If you are querying a large dataset, it's possible to hit the response size limit (1 MB).

I've re-wrote the script to fix the issue above, and have included a snippet to illustrate how to handle the response size limit:

function getRequirementNodes(continuationToken) {
  var context = getContext();
  var response = context.getResponse();
  var collection = context.getCollection();
  var collectionLink = collection.getSelfLink();
  var nodesBatch = [];
  var lastContinuationToken;
  var responseSize = 0;

  var query = {
    query: 'SELECT * FROM root'
  };

  getNodes(continuationToken);

  function getNodes(continuationToken) {
    // Tune the pageSize to fit your dataset.
    var requestOptions = {
      continuation: continuationToken,
      pageSize: 1
    };

    var accepted = collection.queryDocuments(collectionLink, query, requestOptions,
      function(err, documentsRead, responseOptions) {
        // The size of the current query response page.
        var queryPageSize = JSON.stringify(documentsRead).length;

        // DocumentDB has a response size limit of 1 MB.
        if (responseSize + queryPageSize < 1024 * 1024) {
          // Append query results to nodesBatch.
          nodesBatch = nodesBatch.concat(documentsRead);

          // Keep track of the response size.
          responseSize += queryPageSize;

          if (responseOptions.continuation) {
            // If there is a continuation token... Run the query again to get the next page of results
            lastContinuationToken = responseOptions.continuation;
            getNodes(responseOptions.continuation);
          } else {
            // If there is no continutation token, we are done. Return the response.
            response.setBody({
              "message": "Query completed succesfully.",
              "queryResponse": nodesBatch
            });
          }
        } else {
          // If the response size limit reached; run the script again with the lastContinuationToken as a script parameter.
          response.setBody({
            "message": "Response size limit reached.",
            "lastContinuationToken": lastContinuationToken,
            "queryResponse": nodesBatch
          });
        }
      });

    if (!accepted) {
      // If the execution limit reached; run the script again with the lastContinuationToken as a script parameter.
      response.setBody({
        "message": "Execution limit reached.",
        "lastContinuationToken": lastContinuationToken,
        "queryResponse": nodesBatch
      });
    }
  }
}
Andrew Liu
  • 8,045
  • 38
  • 47
  • Seems like the [response size limit has been increased to 4MB in 2016 per this SO post](https://stackoverflow.com/a/40164897/175679). Hard to find hard resource limits posted anywhere for [server-side bounded execution](https://learn.microsoft.com/en-us/azure/cosmos-db/programming#bounded-execution). – SliverNinja - MSFT Feb 14 '18 at 16:53