Skip to content

Project overview

This page describes the context in which the REST API is deployed, as well as a rough structure of the codebase.

Context of the REST API

For Core Contributors

If you are an OpenML core contributor, more information on the services and how they are deployed is available in an internal wiki. Please reach out to in the #core Slack channel for access.

The REST API should always be deployed with access to a database. In production, these services are deployed in a Kubernetes cluster. A typical request flow would then follow this pattern:

sequenceDiagram
    actor Client

    box Server
    participant REST API
    actor Database@{ "type" : "database" }
    end

    Client->> REST API: `GET /datasets/1`
    REST API ->> Database: Query Database
    Database -->> REST API: Results
    REST API ->> REST API: Check Access
    alt Access Granted
        opt Fetch More Data
            REST API ->> Database: Query Database
            Database -->> REST API: Results
        end
        REST API ->> REST API: Format Response
        REST API -->> Client: `HTTP 200 {"dataset_id": ...}`
    else Access Denied
        alt No Credentials
            REST API -->> Client: `HTTP 401 {"type": ...}`
        else Not Allowed
            REST API -->> Client: `HTTP 403 {"type": ...}`
        end
    end

Note that authentication or authorization is required primarily for operations which mutate the database in some way (uploading, tagging, ...). Besides the REST API and the database, the server will also have a number of auxiliary services deployed which support background processes on incoming data:

  • An Evaluation Engine analyzes uploaded datasets to compute its "features" and "qualities" , processes uploaded runs to create "evaluations" and creates task splits. Some of these actions update database state (through calling REST API endpoints).
  • A MinIO server server for file storage. The REST API will stores uploaded datasets and runs there (not yet implemented).
  • An Elastic Search server (see "Elasticsearch" below).
  • A service which creates a Croissant metadata file for a new dataset.
  • A service which converts uploaded ARFF datasets to Parquet (to be phased out as ARFF is phased out).

Elasticsearch

We have Elasticsearch (ES) indices which reflect the state of the database and make it easily accessible to e.g., the website. The PHP-based REST API directly inserts documents into the ES indices. This is problematic because:

  • The REST API will return errors if the Elasticsearch service is unavailable, depending on the endpoint, this results in:
    • the request being stopped early with an error, even if otherwise it would successfully complete the request.
    • the request completes the request, but then returns an error anyway because of the failure to update the ES index. The user is unaware that his request actually succeeded.
  • The REST API has no job queue for inserting these documents, which means if it fails once it is not inserted again, potentially leading to an out-of-sync index.
  • If the ES service is available, the internal roundtrip to update the index adds to server response times.

For these reasons, this REST API implementation will not directly connect to Elasticsearch for creating or updating indices. Instead, we will use e.g., a Logstash pipeline to construct and update the indices directly from the database or make use of a Message Bus. Because a Message Bus keeps some of the disadvantages listed above, we're more likely to use the Logstash approach. The database schema does not accommodate this well, however. For example, there is generally no way to tell which data is removed or updated. In practice, this means that initially the Logstash pipeline will just recreate the indices periodically.

In Phase 3 we can update the schema to work better with Logstash.

The REST API may make use of ES in the future for e.g., list operations. These operations which list lots of data aggregated from many different tables would be considerably faster if we query them from a preconstructed index instead.

For more info, see issue#233.

Authentication

Authentication is currently supported by providing an api key as a query parameter (mimicking the PHP REST API). To avoid accidentally leaking credentials (e.g., with an HTTP request, or our server access logs), we will move this form of authentication to the HTTP header, see issue#203. Ultimately, it would be good to use a dedicated service for authentication, preferably with OAuth, see issue#69(externalizing authentication).

Repository Directory Structure

The diagrams below can be used as a rough indication for the repository file structure. Many subdirectories and files are omitted to highlight the structure rather than specific content. Omissions are not explicitly mentioned in the diagram. The structure of the src/ directory is documented in "Writing Code" and that of the tests/ directory in "Writing Tests".

treeView-beta
 .github/
   workflows/  ## CI/CD scripts
   ISSUE_TEMPLATE/  ## GH issue creation prompt and templates
   PULL_REQUEST_TEMPLATE.md
 docker/  ## For building and configuring containers
   docs/
     Dockerfile  ## For these doc pages
   php/
     .env  ## Configuration of the PHP REST API container
   python/
     Dockerfile  ## For this REST API
 docs/  ## Source for this documentation
   development/
     project_overview.md  ## This file
 src/
   main.py      ## REST API entrypoint
   config.toml  ## REST API configuration
 tests/
 .pre-commit-config.yaml
 codecov.yaml  ## codecov CI configuration
 compose.yaml
 mkdocs.yaml  ## Documentation Configuration
 pyproject.toml  ## Project metadata, dependencies