Retrieving API Results
Most endpoints in the RouteCloud API, when invoked, start a task in RouteCloud. You can retrieve the results of the operation from RouteCloud using one of two techniques, using deferred or immediate results. See the table below for a summary of the two techniques:
Technique | Summary |
---|---|
Deferred | API default. Endpoints return a task id that you can use later to retrieve the results of the operation. |
Immediate | Enabled if the query parameter wait=1 is part of the endpoint request. The request returns the results of the operation immediately, timing out after 15 seconds. |
Choosing which technique to use depends on the type of request and the nature of the use case. If you are unsure, then we recommend to use the deferred technique.
Deferred Results
Endpoints in the RouteCloud API, by default, defer the return of operation results back to the client by returning a task id in response to the initial request from the client. The client can then use this task id to poll RouteCloud API for the completion of the operation and download the results from the RouteCloud API if the operation has finished.
We recomment using deferred results in the following scenarios:
- Long running requests
- Batch operations
- Operations requested as part of a UX interaction
Deferred Results Workflow
In this workflow, requests to RouteCloud endpoints receive a task_redirect_response
reply if the request has been accepted for processing:
HTTP/1.1 200 OK
Content-Type: application/json
{
"task_id": "v4AQjZm1eUW0gFnECtxqAw",
"started_time": "2017-11-23T12:42:23.839Z",
"wait_url": "tasks/v4AQjZm1eUW0gFnECtxqAw/result?wait=1",
"status_url": "tasks/v4AQjZm1eUW0gFnECtxqAw"
}
Clients should then poll the status_url
in from the task_redirect_response
for a task_status_response
until the operation is complete:
HTTP/1.1 200 OK
Content-Type: application/json
{
"task_id": "v4AQjZm1eUW0gFnECtxqAw",
"status": "running",
"started_time": "2017-11-23T12:42:23.839Z",
"latest_status_time": "2017-11-23T12:48:23.839Z",
"status_information": {
"build_phase": 1,
"num_build_phases": 1,
"optimizer_state": "generating_route_options",
"current_state_percent_complete": 6.0,
"aggregates": {
"num_routes": 0,
"num_unassigned_jobs": 0,
"num_violations": 0
}
}
}
When the status
field of the task_status_response
is completed
, the results of the operation can be downloaded by fetching the URL in the wait_url
field of the task_redirect_response
.
Note
The results of the operation are stored on the server for only six hours.
Code Examples - Deferred Results
/**
* This example requires the following nuget packages:
* Newtonsoft.Json
*/
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace DeferredResults {
class Program {
static async Task Main(string[] args) {
Uri baseRouteCloudUri = new Uri("https://routecloud.telogis.com/v1");
var httpClient = new HttpClient();
// Prepare routecloud operation
var (endpoint, content) = PrepareRouteCloudTask();
// Do the initial request to routecloud
var initialResponse = await httpClient.PostAsync(new Uri(baseRouteCloudUri, endpoint), content);
var rcTaskDetails = JToken.Parse(await initialResponse.Content.ReadAsStringAsync());
var rcTaskId = (string)rcTaskDetails["task_id"]; // Log this field or save for later
var statusUrl = new Uri(baseRouteCloudUri, (string)rcTaskDetails["status_url"]);
var resultUrl = new Uri(baseRouteCloudUri, (string)rcTaskDetails["wait_url"]);
bool completed = false;
while (!completed) {
var statusResponse = JToken.Parse(await httpClient.GetStringAsync(statusUrl));
completed = (string)statusResponse["status"] == "completed";
}
var result = await httpClient.GetStringAsync(resultUrl);
Console.WriteLine($"Result: {result}");
Console.WriteLine("Finished");
}
public static (string endpoint, HttpContent content) PrepareRouteCloudTask() {
// TODO: Prepare the RouteCloud task here
return ("", null);
}
}
}
Immediate Results
If the URL parameter wait=1
is part of a request to the RouteCloud API, the response from the API is the result of the operation requested. If the operation takes longer than 15 seconds, the response from the API is a 302 redirect to a new URL that you can poll for the result.
We recommend using immediate results only for those operations that take a short time to complete, ideally within 15 seconds.
Immediate Results Workflow
A request using the immediate result workflow to a RouteCloud API endpoint receives in reply the result of the operation if the operation completes within 15 seconds. Otherwise, the endpoint replies with a task_redirect_response
as a HTTP 302 redirect:
HTTP/1.1 302 Found
Location: tasks/v4AQjZm1eUW0gFnECtxqAw&wait=1
Content-Type: application/json
{
"task_id": "v4AQjZm1eUW0gFnECtxqAw",
"started_time": "2017-11-23T12:42:23.839Z",
"wait_url": "tasks/v4AQjZm1eUW0gFnECtxqAw&wait=1",
"status_url": "tasks/v4AQjZm1eUW0gFnECtxqAw"
}
Following the 302 redirect URL, causes the same behavior to be repeated: The server returns the results of the operation if the operation is available within 15 seconds. Otherwise, another 302 redirect is issued.
Note
Most HTTP libraries attempt to follow the 302 redirects automatically. However, almost all libraries have default request timeouts and redirect attempts that might be exceeded if the operation takes too long. Therefore, we highly recommend that you disable the automatic redirection in the HTTP library and manually poll the redirect URL using a loop or similar.
Code Examples - Immediate Results
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
namespace ImmediateResults {
class Program {
static async Task Main(string[] args) {
Uri baseRouteCloudUri = new Uri("https://routecloud.telogis.com/v1");
var httpClient = new HttpClient(new HttpClientHandler {
AllowAutoRedirect = false // Disable automatic redirect to avoid hitting redirect limits
});
// Prepare routecloud task
var (endpoint, httpContent) = PrepareRouteCloudTask();
// Configure the url for immediate results workflow
var uriBuilder = new UriBuilder(new Uri(baseRouteCloudUri, endpoint));
var queryParams = HttpUtility.ParseQueryString(uriBuilder.Query);
queryParams["wait"] = "1";
uriBuilder.Query = queryParams.ToString();
bool completed = false;
var redirectUri = uriBuilder.Uri;
while (!completed) {
var response = await httpClient.GetAsync(redirectUri);
if (response.StatusCode == System.Net.HttpStatusCode.Redirect) {
redirectUri = new Uri(baseRouteCloudUri, response.Headers.Location);
} else {
completed = true;
if (response.StatusCode == System.Net.HttpStatusCode.OK) {
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Result: {result}");
}
}
}
Console.WriteLine("Finished");
}
public static (string endpoint, HttpContent content) PrepareRouteCloudTask() {
// Prepare the RouteCloud task here
return ("", null);
}
}
}
Endpoints
List
Retrieve the list of current tasks using GET
/v1/tasks.
Status
Retrieve the status of a task using GET
/v1/tasks/{task_id}.
Result
Retrieve the result of a task using GET
/v1/tasks/{task_id}/result?wait=1.
Cancel
Cancel a task using POST
/v1/tasks/{task_id}/cancel.