Toggle menu

Asynchronous API Server Calls

The API Server supports asynchronous requests. This allows tasks to be performed in the future, while the client receives an initial response and can move on.

Normal requests to the API Server are performed synchronously, with the client waiting for a response. The execution time of these requests is limited to two minutes. For some requests, like the importing or exporting of large amounts of data, two minutes may not allow enough time for the request to complete.

Asynchronous requests return a near immediate result which confirms the request has been accepted and allows the client to move on. At some point in the future the API Server will pass the request to the relevant worker, wait for the response, and, depending upon the request, may pass the results of the request to another worker specified in the callback property of the original request.

Flow of Requests During Asynchronous API Server Calls
 

The image above shows three distinct stages of execution.

  1. The client makes a request to the API Server and receives a response (which includes a unique request ID)
  2. The API Server passes the request to the target worker, which returns a response to the API Server when complete
  3. If details of a callback worker were provided in the initial request, the API Server passes the response (from step two) to that worker

There's an example set of End Points making asynchronous requests in the Asynchronous End Point Framework article.

Making an Asynchronous Request _async

To make an asynchronous request, include the _async object parameter with your request.

Example Request

In this example we are making an asynchronous request to the Email Worker. All of the usual parameters are passed to the sendemail method, plus an empty _async object.

Note that performing this request asynchronously serves no real purpose!

var email = client.invoke("email", "sendmail", {
    "_async": {},
    "from":  {
        "address": "frommysite@mysite.com"
    },
    "to":  {
        "address": "toyou@you.com"
    },
    "subject": {
        "text": "The Subject Line"
    },
    "body": {
        "text" : "The body of the email"
    }
});

Example Response

Our result from the API Server is the asyncRequestId. The Email Worker is called at some point in the future.

{
    "jsonrpc": "2.0",
    "id": 33,
    "result": {
        "id": "_138",
        "jsonrpc": "2.0",
        "result": {
            "asyncRequestId": "06650874-fe15-4ab5-be33-566b30e04f78",
            "asyncCallerId": ""
        }
    }
}

The _async Object and Callback Properties

Our asynchronous request can include callback options which can pass the result of the request to another worker. The callback worker is typically an End Point, which will then "do something" with the result.

Property NameTypeDescription
asyncCallerIdString, optionalAn optional ID for the request. The value will be returned alongside the asyncRequestId
callbackObject, optionalThe callback object
callback.workerNameStringThe name of a worker on the API Server where the request is being made

Either workerName or servicePath must be supplied
callback.servicePathStringA complete URL. This could be a complete path to an API Server and worker (perhaps a remotely hosted API Server) or another service that accepts JSON RPC

Either workerName or servicePath must be supplied
callback.methodNameString, requiredThe name of the method to be invoked
callback.apikeyString, optionalAn API key to use in the callback request
callback.UserString, optionalA username to use in the callback request
callback.PasswordString, optionalA password to use in the callback request
callback.responseParamNameString, optionalAn alternative name for the "response" parameter in the callback request
callback.additionalParamsObject, optionalAny additional parameters to supply with the callback request

Example Request

In this example we make an asynchronous request to an End Point called example.query.

var resp = client.invoke("serverlibrary", "example.query", {
    "_async": {
        "callback": {
            "workerName": "serverlibrary",
            "methodName": "example.callback",
            "additionalParams": {
                "additionalName": "additionalValue"
            }
        }
    }
});

The request returns an immediate response to the client:

{
    "jsonrpc": "2.0",
    "id": 72,
    "result": {
        "id": "_180",
        "jsonrpc": "2.0",
        "result": {
            "asyncRequestId": "a5e4e753-ca68-4155-baf5-c7e6336072c1",
            "asyncCallerId": ""
        }
    }
}

The API Server then makes a request to the example.query End Point.

Once that request has completed, the API Server passes the result to our example.callback EndPoint in a response parameter. Note the inclusion of the additional parameters from our original request.

{
    "params": {
        "​​​​​​additionalName": "additionalValue",
        "response": {
            "jsonrpc": "2.0", 
           "id": "_442", 
            "result": [
                {
                   "The result of whatever my query was..."
                }, 
           ]
        }
    }
}

Working With The Response

In the example above our example.callback EndPoint could invoke the API Server's Email Worker to send an email.

Here the Email Worker is being passed fixed values for the "to" and "subject" parameters, and the response from the example.query End Point as the email body.

var result = client.invoke("email", "sendmail", {
    "to": {
        "address": "somone@gossinteractive.com"
    },
    "subject": {
        "text": "Subject line"
    },
    "body": {
        "text": JSON.stringify(params.response.result)
    },
});
return result;

Last modified on 16 January 2019

Share this page

Facebook icon Twitter icon email icon

Print

print icon