HTTP Interface for Async Results Management
Request Execution
ArangoDB provides various methods of executing client requests. Clients can choose the appropriate method on a per-request level based on their throughput, control flow, and durability requirements.
Blocking execution
ArangoDB is a multi-threaded server, allowing the processing of multiple client requests at the same time. Communication handling and the actual work can be performed by multiple worker threads in parallel.
Though multiple clients can connect and send their requests in parallel to ArangoDB, clients may need to wait for their requests to be processed.
By default, the server will fully process an incoming request and then return the result to the client. The client must wait for the server’s response before it can send additional requests over the connection. For clients that are single-threaded or not event-driven, waiting for the full server response may be non-optimal.
Furthermore, please note that even if the client closes the HTTP connection, the request running on the server will still continue until it is complete and only then notice that the client no longer listens. Thus closing the connection does not help to abort a long running query! See below under Async Execution and later Result Retrieval and HttpJobPutCancel for details.
Fire and Forget
To mitigate client blocking issues, ArangoDB since version 1.4. offers a generic mechanism for non-blocking requests: if clients add the HTTP header x-arango-async: true to their requests, ArangoDB will put the request into an in-memory task queue and return an HTTP 202 (accepted) response to the client instantly. The server will execute the tasks from the queue asynchronously, decoupling the client requests and the actual work.
This allows for much higher throughput than if clients would wait for the server’s response. The downside is that the response that is sent to the client is always the same (a generic HTTP 202) and clients cannot make a decision based on the actual operation’s result at this point. In fact, the operation might have not even been executed at the time the generic response has reached the client. Clients can thus not rely on their requests having been processed successfully.
The asynchronous task queue on the server is not persisted, meaning not-yet processed tasks from the queue will be lost in case of a crash. However, the client will not know whether they were processed or not.
Clients should thus not send the extra header when they have strict durability requirements or if they rely on result of the sent operation for further actions.
The maximum number of queued tasks is determined by the startup option --server.maximal-queue-size. If more than this number of tasks are already queued, the server will reject the request with an HTTP 500 error.
Finally, please note that it is not possible to cancel such a fire and forget job, since you won’t get any handle to identify it later on. If you need to cancel requests, use Async Execution and later Result Retrieval and HttpJobPutCancel below.
Async Execution and later Result Retrieval
By adding the HTTP header x-arango-async: store to a request, clients can instruct the ArangoDB server to execute the operation asynchronously as above, but also store the operation result in memory for a later retrieval. The server will return a job id in the HTTP response header x-arango-async-id. The client can use this id in conjunction with the HTTP API at /_api/job, which is described in detail in this manual.
Clients can ask the ArangoDB server via the async jobs API which results are ready for retrieval, and which are not. Clients can also use the async jobs API to retrieve the original results of an already executed async job by passing it the originally returned job id. The server will then return the job result as if the job was executed normally. Furthermore, clients can cancel running async jobs by their job id, see HttpJobPutCancel.
ArangoDB will keep all results of jobs initiated with the x-arango-async: store header. Results are removed from the server only if a client explicitly asks the server for a specific result.
The async jobs API also provides methods for garbage collection that clients can use to get rid of “old” not fetched results. Clients should call this method periodically because ArangoDB does not artificially limit the number of not-yet-fetched results.
It is thus a client responsibility to store only as many results as needed and to fetch available results as soon as possible, or at least to clean up not fetched results from time to time.
The job queue and the results are kept in memory only on the server, so they will be lost in case of a crash.
Canceling asynchronous jobs
As mentioned above it is possible to cancel an asynchronously running job using its job ID. This is done with a PUT request as described in HttpJobPutCancel.
However, a few words of explanation about what happens behind the scenes are in order. Firstly, a running async query can internally be executed by C++ code or by JavaScript code. For example CRUD operations are executed directly in C++, whereas AQL queries and transactions are executed by JavaScript code. The job cancelation only works for JavaScript code, since the mechanism used is simply to trigger an uncatchable exception in the JavaScript thread, which will be caught on the C++ level, which in turn leads to the cancelation of the job. No result can be retrieved later, since all data about the request is discarded.
If you cancel a job running on a Coordinator of a cluster (Sharding), then only the code running on the Coordinator is stopped, there may remain tasks within the cluster which have already been distributed to the DB-Servers and it is currently not possible to cancel them as well.
Async Execution and Authentication
If a request requires authentication, the authentication procedure is run before queueing. The request will only be queued if it valid credentials and the authentication succeeds. If the request does not contain valid credentials, it will not be queued but rejected instantly in the same way as a “regular”, non-queued request.
Managing Async Results via HTTP
Return result of an async job
fetches a job result and removes it from the queue
PUT /_api/job/{job-id}
Path Parameters
- job-id (string, required): The async job id.
Returns the result of an async job identified by job-id. If the async job result is present on the server, the result will be removed from the list of result. That means this method can be called for each job-id once. The method will return the original job result’s headers and body, plus the additional HTTP header x-arango-async-job-id. If this header is present, then the job was found and the response contains the original job’s result. If the header is not present, the job was not found and the response contains status information from the job manager.
Responses
HTTP 204: is returned if the job requested via job-id is still in the queue of pending (or not yet finished) jobs. In this case, no x-arango-async-id HTTP header will be returned.
HTTP 400: is returned if no job-id was specified in the request. In this case, no x-arango-async-id HTTP header will be returned.
HTTP 404: is returned if the job was not found or already deleted or fetched from the job result list. In this case, no x-arango-async-id HTTP header will be returned.
Examples Not providing a job-id:
shell> curl -X PUT --header 'accept: application/json' --dump - http://localhost:8529/_api/job
HTTP/1.1 400 Bad Request
content-type: application/json
connection: Keep-Alive
content-length: 71
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Providing a job-id for a non-existing job:
shell> curl -X PUT --header 'accept: application/json' --dump - http://localhost:8529/_api/job/notthere
HTTP/1.1 404 Not Found
content-type: application/json
connection: Keep-Alive
content-length: 67
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Fetching the result of an HTTP GET job:
shell> curl -X PUT --header 'x-arango-async: store' --header 'accept: application/json' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81774
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl -X PUT --header 'accept: application/json' --dump - http://localhost:8529/_api/job/81774
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 60
server: ArangoDB
x-arango-async-id: 81774
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Fetching the result of an HTTP POST job that failed:
shell> curl -X PUT --header 'x-arango-async: store' --header 'accept: application/json' --data-binary @- --dump - http://localhost:8529/_api/collection <<EOF
{
"name" : " this name is invalid "
}
EOF
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81776
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl -X PUT --header 'accept: application/json' --dump - http://localhost:8529/_api/job/81776
HTTP/1.1 400 Bad Request
content-type: application/json
connection: Keep-Alive
content-length: 114
server: ArangoDB
x-arango-async-id: 81776
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Cancel async job
cancels an async job
PUT /_api/job/{job-id}/cancel
Path Parameters
- job-id (string, required): The async job id.
Cancels the currently running job identified by job-id. Note that it still might take some time to actually cancel the running async job.
Responses
HTTP 200: cancel has been initiated.
HTTP 400: is returned if no job-id was specified in the request. In this case, no x-arango-async-id HTTP header will be returned.
HTTP 404: is returned if the job was not found or already deleted or fetched from the job result list. In this case, no x-arango-async-id HTTP header will be returned.
Examples
shell> curl -X POST --header 'x-arango-async: store' --header 'accept: application/json' --data-binary @- --dump - http://localhost:8529/_api/cursor <<EOF
{
"query" : "FOR i IN 1..10 FOR j IN 1..10 LET x = sleep(1.0) FILTER i == 5 && j == 5 RETURN 42"
}
EOF
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81761
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl --header 'accept: application/json' --dump - http://localhost:8529/_api/job/pending
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 9
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl -X PUT --header 'accept: application/json' --dump - http://localhost:8529/_api/job/81761/cancel
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 15
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl --header 'accept: application/json' --dump - http://localhost:8529/_api/job/pending
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 9
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Deletes async job
deletes an async job result
DELETE /_api/job/{type}
Path Parameters
- type (string, required):
The type of jobs to delete. type can be:
- all: Deletes all jobs results. Currently executing or queued async jobs will not be stopped by this call.
- expired: Deletes expired results. To determine the expiration status of a result, pass the stamp query parameter. stamp needs to be a UNIX timestamp, and all async job results created at a lower timestamp will be deleted.
- an actual job-id: In this case, the call will remove the result of the specified async job. If the job is currently executing or queued, it will not be aborted.
Query Parameters
- stamp (number, optional): A UNIX timestamp specifying the expiration threshold when type is expired.
Deletes either all job results, expired job results, or the result of a specific job. Clients can use this method to perform an eventual garbage collection of job results.
Responses
HTTP 200: is returned if the deletion operation was carried out successfully. This code will also be returned if no results were deleted.
HTTP 400: is returned if type is not specified or has an invalid value.
HTTP 404: is returned if type is a job-id but no async job with the specified id was found.
Examples
Deleting all jobs:
shell> curl -X PUT --header 'x-arango-async: store' --header 'accept: application/json' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81765
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl -X DELETE --header 'accept: application/json' --dump - http://localhost:8529/_api/job/all
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 15
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Deleting expired jobs:
shell> curl -X PUT --header 'x-arango-async: store' --header 'accept: application/json' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81767
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl --header 'accept: application/json' --dump - http://localhost:8529/_admin/time
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 55
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl -X DELETE --header 'accept: application/json' --dump - http://localhost:8529/_api/job/expired?stamp=1652867776.4361026
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 15
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl --header 'accept: application/json' --dump - http://localhost:8529/_api/job/pending
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 2
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Deleting the result of a specific job:
shell> curl -X PUT --header 'x-arango-async: store' --header 'accept: application/json' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81769
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl -X DELETE --header 'accept: application/json' --dump - http://localhost:8529/_api/job/81769
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 15
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Deleting the result of a non-existing job:
shell> curl -X DELETE --header 'accept: application/json' --dump - http://localhost:8529/_api/job/AreYouThere
HTTP/1.1 404 Not Found
content-type: application/json
connection: Keep-Alive
content-length: 67
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Returns async job
Returns the status of a specific job
GET /_api/job/{job-id}
Path Parameters
- job-id (string, required): The async job id.
Returns the processing status of the specified job. The processing status can be determined by peeking into the HTTP response code of the response.
Responses
HTTP 200: is returned if the job requested via job-id has been executed and its result is ready to fetch.
HTTP 204: is returned if the job requested via job-id is still in the queue of pending (or not yet finished) jobs.
HTTP 404: is returned if the job was not found or already deleted or fetched from the job result list.
Examples
Querying the status of a done job:
shell> curl -X PUT --header 'x-arango-async: store' --header 'accept: application/json' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81785
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl -X PUT --header 'accept: application/json' --dump - http://localhost:8529/_api/job/81785
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 60
server: ArangoDB
x-arango-async-id: 81785
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Querying the status of a pending job: (therefore we create a long runnging job…)
shell> curl -X POST --header 'x-arango-async: store' --header 'accept: application/json' --data-binary @- --dump - http://localhost:8529/_api/transaction <<EOF
{
"collections" : {
"read" : [
"_aqlfunctions"
]
},
"action" : "function () {require('internal').sleep(15.0);}"
}
EOF
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81787
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl --header 'accept: application/json' --dump - http://localhost:8529/_api/job/81787
HTTP/1.1 204 No Content
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Returns list of async jobs
Returns the ids of job results with a specific status
GET /_api/job/{type}
Path Parameters
- type (string, required): The type of jobs to return. The type can be either done or pending. Setting the type to done will make the method return the ids of already completed async jobs for which results can be fetched. Setting the type to pending will return the ids of not yet finished async jobs.
Query Parameters
-
count (number, optional):
The maximum number of ids to return per call. If not specified, a server-defined maximum value will be used.
Returns the list of ids of async jobs with a specific status (either done or pending). The list can be used by the client to get an overview of the job system status and to retrieve completed job results later.
Responses
HTTP 200: is returned if the list can be compiled successfully. Note: the list might be empty.
HTTP 400: is returned if type is not specified or has an invalid value.
Examples
Fetching the list of done jobs:
shell> curl -X PUT --header 'x-arango-async: store' --header 'accept: application/json' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81778
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl --header 'accept: application/json' --dump - http://localhost:8529/_api/job/done
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 9
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
Fetching the list of pending jobs:
shell> curl -X PUT --header 'x-arango-async: store' --header 'accept: application/json' --dump - http://localhost:8529/_api/version
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81780
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl --header 'accept: application/json' --dump - http://localhost:8529/_api/job/pending
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 2
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
[ ]
Querying the status of a pending job: (we create a sleep job therefore…)
shell> curl -X POST --header 'x-arango-async: store' --header 'accept: application/json' --data-binary @- --dump - http://localhost:8529/_api/transaction <<EOF
{
"collections" : {
"read" : [
"_frontend"
]
},
"action" : "function () {require('internal').sleep(15.0);}"
}
EOF
HTTP/1.1 202 Accepted
content-type: text/plain
connection: Keep-Alive
content-length: 0
server: ArangoDB
x-arango-async-id: 81782
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl --header 'accept: application/json' --dump - http://localhost:8529/_api/job/pending
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 9
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff
shell> curl -X DELETE --header 'accept: application/json' --dump - http://localhost:8529/_api/job/81782
HTTP/1.1 200 OK
content-type: application/json
connection: Keep-Alive
content-length: 15
server: ArangoDB
x-arango-queue-time-seconds: 0.000000
x-content-type-options: nosniff