GSP Request Succession

A GSP request can specify that its successful completion should be succeeded by further requests by including a Successor-Location header which locates their query texts.

Successor Request Form

The successor SPARQL request is recorded in the form of an HTTP asynchronous request which captures the SPARQL expression and execution arguments. This includes the same headers as for an asynchronous GSP request and adds several headers specific to successor requests. (See Asynchronous Request Form .)

Successor-Content-Type

Provides the media type for the query expression. The default is application/sparql-query.

Successor-Location

A space delimited list of HTTP URL values which locate the query text(s). Each can be a local view identifier or that of a remote source.

Successor-Revision-ID

Identifies the repository revision which the successor request is to target. If none is supplied, the successor request targets the revision upon completion of the initial request.

Example

curl_graph_store_update -X PUT -o /dev/null \
   -H "Content-Type: application/rdf+json" \
   -H "Successor-Location: https://localhost/${STORE_ACCOUNT}/${STORE_REPOSITORY}-write/count-all" \
   -H "Successor-Content-Type: application/sparql-query" \
   -H "Asynchronous-Content-Type: application/n-quads" \
   -H "Asynchronous-Location: https://localhost/${STORE_ACCOUNT}/${STORE_REPOSITORY}-write/service" \
   -H "Asynchronous-Method: POST" \
   --repository "${STORE_REPOSITORY}-write" <<EOF
{ "http://example.com/default-subject" : {
  "http://example.com/default-predicate" : [ { "value" : "default object PUT-successor",
                                               "type" : "literal" } ]
  }
}
EOF

If the location header specifies multiple URLs, each serves to locate the content of a successor asynchronous request. They must share the same media type and revision id.

For more extensive examples, refer to the HTTP API tests.

Discussion

A successor request content is taken from the given location. This can be a local view url, in which case the view provides the SPARQL expression. It can also be an arbitrary remote location, in which an HTTP request retrieves the SPARQL text and relevant values are adopted from the response headers.

A revision id UUID value is specified for the successor request to cause it to target a specific repository revision, for example ‘HEAD’. If none is specified, that revision which was current at the conclusion of the original request is adopted and supplied to the successor. For a graph store update request or a sparql update request, this is the id of the respective write transaction.

In order to make the repository state and any response headers consistent, the ETag response header for a SPARQL update and GSP update now reflect this same logic: the same UUID value appears in both response ETag header of the initial request and in the Revision-Id header of the successor request.

For GSP update requests, this is taken from the revision record which is produced by the import process. That record’s UUID is used for the ETag, which makes it available when constructing the headers to be used be the successor event.

For a SPARQL update requests, the id is the transaction identifier of the request itself.

Note that the request succession is just in terms of control-flow. The result data-flow follows that of the asynchronous extensions to the HTTP protocol. The request data-flow adds just the logic associated with the Successor-Location. ### internal operators

Any remote query text is retrieved with the call-with-http-response-stream operator from the HTTP server library.

Alternatives

One requirement which led to this approach is the desire to minimize the client implementation. This requiremnt is satisified in that the approach combines just three additional HTTP request headers with the asynchronous processing pattern.

One principal alternative is to extend a client implementation with a means to declare compound requests and to interpret their results. Many variations exist.

  • Microsoft’s json batching relies on client logic to generate compound requests as json documents and to destructure responses.

  • Insomnia’s chaining includes that ability to use the output of an initial request as the content for a successor as well as to incorporate response header values in the successor request.

  • Postman includes a similar capability for constructing tests as request chains in its request script facility.

  • NGINX provides in intermediate approach in the form of a JavaScript module which can be used to execute batched sub-requests

  • JavaScript itself allows to chain fetch invocations in order to coordinate requests and frameworks provide more abstract orchestration methods, such as Angular’s mergeMap operator.

  • Facebook’s Graph API provides the means to “pass instructions for several operations in a single HTTP request.” The response is a collation of the respective responses.

  • iOS Swift includes the constrol structure operator Combine which can be used to orchestrate HTTP requests and responses.

Another alternative would to collect the requests into a multipart/related document and provide similar means to propagate state from an initial request to its successors.

Within a SPARQL processor, UPDATE forms do allow an operation sequence, but are limited to modifications, which elliminates arbitrary query results.