Skip to main content

Long-Polling Agent-to-Internet Communications

Recommended Code Flow For Making Long-polling HTTP Requests

When the agent makes an HTTP request to a remote service that is known to take a significant amount of time to respond, the agent code can take advantage of optional method parameters to deal with the situation. This is a technique called ‘long polling’ and its often required when the remote service has itself to contact other services, or the initial request is made to a service which is emulating a push server. In each case, any response is likely to return well beyond the limits of a typical request timeout.

The basics of making HTTP requests are covered in the recipe Basic Agent-to-Internet Communications and this recipe builds on that one. For long-polling requests, the CPU-blocking imp API method httprequest.sendsync() is inappropriate so the long-polling options are limited to asynchronous response handling, provided by httprequest.sendasync().

The httprequest.sendasync() method takes two optional parameters in addition to the mandatory function that will be called when a short-term (under 60 seconds) response is received. The first is the function to be called when the long-term response is received. This may be the same function nominated in the first parameter. Either or both callbacks may be inline functions. However the functions are defined, both must include a single parameter into which a table containing the remote service’s response (or an error) will be placed.

The third parameters is a long-polling timeout in seconds. The default value is 600 (ten minutes). To disable the timeout, set the parameter to the constant NO_TIMEOUT.

Sample Code

The following code snippet shows the creation and transmission of a simple HTTP GET request with a long polling function to a remote service that delivers push notifications. The request is made in the usual way, but the code contains two callback functions: one for the remote service's initial acknowledgement of the request, the other for the long-poll response. We use the default timeout of 600 seconds.

If the initial acknowledgement times out or results in an error, the code cancels the request; if the server ever responds, it will be ignored. When the long-poll response is received, the code automatically queues up a fresh long-poll request to catch the next ‘push’ notification from the remote service.

// Set up outgoing request object as a global (we may need to cancel it, so we need a reference to it)
request <- http.get(webServiceURL, webServiceHeaders);
// Define the response handler
function handleResponse(responseTable) {
// Called when the imp receives an immediate acknowledgement from the remote service
if (responseTable.statuscode == 200) {
// Remote service has responded with 'OK' so decode
// the response's body 'responseTable.body' and headers 'responseTable.headers'
// Code omitted for clarity...
} else {
// Log an error
server.log("Error response: " + responseTable.statuscode);
// And cancel the request (since the remote server clearly can't fulfil the push request)
request.cancel();
}
}
// Define the long-poll response handler
function handleLongResponse(responseTable) {
// Called when the imp receives a long-term response from the remote service
// This might be information 'pushed' to the device, so we need to re-submit
// the request in order to receive future notifications
if (responseTable.statuscode == 200) {
// Remote service has responded with 'OK' so decode
// the response's body 'responseTable.body' and headers 'responseTable.headers'
// Code omitted for clarity...
} else {
// Log an error
server.log("Error response: " + responseTable.statuscode);
}
// Re-submit the long-poll request. We must initialize a new request for this
request = http.get(webServiceURL, webServiceHeaders);
request.sendasync(handleResponse, handleLongResponse);
}
// Send the request asynchronously. This will not block the imp CPU
request.sendasync(handleResponse, handleLongResponse);

API Properties Used

API Methods Used

Further Reading