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 metadata

    • Type: SPARQL 1.1 Query Endpoint

    • GET or POST - execute the SPARQL query against the Metadata graph belonging to the repo corresponding with orgId and projectId

    • OPTIONS - for CORS preflighted requests

    • HEAD (without any query parameters) - No-op

  • /orgs/{orgId}/repos/{repoId}/locks/{lockId}/query – query a model given by the specified lock

    • Type: SPARQL 1.1 Query Endpoint

    • GET or POST - execute the SPARQL query against the lock having the given lockId which belongs to the repo corresponding with orgId and repoId

    • OPTIONS - for CORS preflighted requests

    • HEAD (without any query parameters) - fetch the ETag value that uniquely identifies the current version of the model

  • /orgs/{orgId}/repos/{repoId}/branches/{branchId}/query – query a model given by the specified branch

    • Type: SPARQL 1.1 Query Endpoint

    • GET or POST - execute the SPARQL query against the branch having the given branchId which belongs to the repo corresponding with orgId and repoId

    • OPTIONS - for CORS preflighted requests

    • HEAD (without any query parameters) - fetch the ETag value that uniquely identifies the current version of the model

  • /orgs/{orgId}/repos/{repoId}/branches/{branchId}/update – update a model given by the specified branch

    • Type: SPARQL 1.1 Update Endpoint

    • POST - attempt to apply the SPARQL update against the latest version of the model given branchId which belongs to the project corresponding with orgId and repoId

      • 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 graph

    • Type: SPARQL 1.1 Graph Store Protocol (GSP) Endpoint

    • GET - retrieve the model as RDF given by branchId which belongs to the project corresponding with orgId and repoId

    • POST - merge the uploaded RDF graph with the model given by branchId which belongs to the project corresponding with orgId and repoId

    • 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 on

  • X-MMS-Context-Ref-Id: {REF_ID} - suffix of the resource IRI for the ref that the action was performed on

  • X-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