Virtual Endpoints
Virtual endpoints allow users to scope their SPARQL queries by repo and optionally ref.
For example, to query the latest commit from the develop branch of the TMT repo:
POST /orgs/openmbee/repos/TMT/branches/develop/query HTTP/*
Content-Type: application/x-www-form-urlencoded
query=select+*+where...
Note that in the SPARQL 1.1 Protocol standard, §2.1.4 Specifying an RDF Dataset includes the following statement:
If an RDF Dataset is not specified in either the protocol request or the SPARQL query string, then implementations may execute the query against an implementation-defined default RDF dataset.
Motivation
In Flexo MMS, the graph IRI for each materialized snapshot is an opaque, non-human-readable identifier. Advanced query authors have the ability to query for these graph IRIs and use arbitrary constraints to filter which model(s) get evaluated. For example, to query for a specific graph pattern among any snapshots that materialize commits made in January of 2021:
However, when it comes to simply querying the latest commit of a particular branch, or the materialized snapshot of an existing locked commit, this approach of selecting the right graph IRI before each model query can be cumbersome for query authors. Alternatively, virtual endpoints allow clients to specify the intended dataset by using path parameters in their HTTP request. See example above.
Forbidding the use of named graphs
In order to maintain compatibility with the SPARQL 1.1 Protocol, such virtual endpoints are only allowed to perform this type of dataset inference if the query does not specify any named graphs. If the user does specify a named graph, the implementors of the virtual endpoint may either attempt to honor the request, or deny it. From §2.1.4 Specifying an RDF Dataset:
Note that a service may reject a query with HTTP response code 400 if the service does not allow protocol clients to specify the RDF Dataset.
Denying such requests with a 400 response is the preferred option for virtual endpoints since their primary purpose is to scope (and contextualize) SPARQL queries to a specific named graph. Instead, SPARQL queries that rely on the use named graphs should be directed to the global, ‘non-virtual’ Flexo MMS endpoint.
Virtual endpoint REST API
/orgs/{orgId}/repos/{repoId}/query
– query project metadataGET
orPOST
- execute the SPARQL query against the Metadata graph belonging to the repo corresponding withorgId
andprojectId
OPTIONS
- for CORS preflighted requestsHEAD
(without any query parameters) - No-op
/orgs/{orgId}/repos/{repoId}/locks/{lockId}/query
– query a model given by the specified lockGET
orPOST
- execute the SPARQL query against the lock having the givenlockId
which belongs to the repo corresponding withorgId
andrepoId
OPTIONS
- for CORS preflighted requestsHEAD
(without any query parameters) - fetch theETag
value that uniquely identifies the current version of the model
/orgs/{orgId}/repos/{repoId}/branches/{branchId}/query
– query a model given by the specified branchGET
orPOST
- execute the SPARQL query against the branch having the givenbranchId
which belongs to the repo corresponding withorgId
andrepoId
OPTIONS
- for CORS preflighted requestsHEAD
(without any query parameters) - fetch theETag
value that uniquely identifies the current version of the model
/orgs/{orgId}/repos/{repoId}/branches/{branchId}/update
– update a model given by the specified branchPOST
- attempt to apply the SPARQL update against the latest version of the model givenbranchId
which belongs to the project corresponding withorgId
andrepoId
additional required headers:
X-MMS-Context-Commit: {COMMIT_URI}
OPTIONS
- for CORS preflighted requests
/orgs/{orgId}/repos/{repoId}/branches/{branchId}/graph
– download or upload an entire model as an RDF graphGET
- retrieve the model as RDF given bybranchId
which belongs to the project corresponding withorgId
andrepoId
POST
- merge the uploaded RDF graph with the model given bybranchId
which belongs to the project corresponding withorgId
andrepoId
OPTIONS
- for CORS preflighted requests
Headers schema
An important quality of the virtual endpoint API is the ability to inform clients about which version of the model was used to evaluate their query (and thus which version of the model the returned query results correspond with). Note that the use of an ETag
header in response to a query would serve to cache the results for that particular query without saying anything about the underlying model. However, ETag
can be used in response to a HEAD
request to the base path of a virtual endpoint if no query parameters are used. In fact, several enterprise quadstores will respond to GET
requests to the base path that omit all query parameters with a complete serialization of the underlying graph(s). Operating under this same assumption, a HEAD
request to the base path without query parameters essentially asks “tell me about the model without giving me all its triples”. Therefore, clients can use this method to deduce whether a newer version of the model has become available by comparing the ETag
header values.
However, clients should also receive an identifier in response to queries so that it is clear which model version was used to produce the returned query results. For this, the server shall send the following headers in every response from a virtual endpoint:
X-MMS-Context-Repo-Id: {REPO_ID}
- suffix of the resource IRI for the repo that the action was performed onX-MMS-Context-Ref-Id: {REF_ID}
- suffix of the resource IRI for the ref that the action was performed onX-MMS-Context-Commit-Id: {COMMIT_ID}
- suffix of the resource IRI for the commit that the action was performed on
The following headers are sent in certain circumstances:
X-MMS-Conflict-Commit-Id: {COMMIT_ID}
- when a merge conflict occurs, indicates the offending commit