A modern online judge.
TODO.
TODO.
This section describes the components of the system.
This section describes the backend applications of the system.
An API server is a stateless server providing an API to define and control the entities, or resources, of the system.
Clients who wish to create and manipulate the system resources are able to perform these operations by making requests to the API server. Each client described in this architecture has a dedicated API subset.
Judges are workers consuming a queue of submission executions.
For each job popped from the queue, a judge is fulfilling a request of executing a problem submission, checking whether the outputs of this submission execution are correct and storing this check in the API. When talking to the API servers, a judge uses the judge API subset. For the execution part, the judge performs a request to an execution server.
An execution server is responsible for the critical mission of the system: executing untrusted code. For this, a particular execution server should be as much isolated as possible from everything else. Execution servers should not make requests to the API server directly, instead every required resource from the API should be passed in the execution request parameters by the requesting judge.
For each execution request, an execution server reads the required inputs from the file storage, compiles and executes the untrusted code, writes the associated outputs in the file storage and responds completion to the requesting judge.
The timeout engine is a worker responsible for watching the problem submissions still needing automatic judgement and creating associated submission executions in the timeout API subset.
This section describes the components of the system responsible for storing all sorts of data.
A relational database should store the data behind the resources of the system exposed by the API.
A cache should store the short-living auxiliar data shared by the API servers, like session tokens.
A message broker should act as a queue receiving submission execution jobs from the API servers and delivering those jobs atomically in FIFO order to the judges.
A file storage should store and serve files related to problems and submissions, like source codes, inputs and outputs.
This section describes the user interfaces of the system.
A website for the user to interact with the system. The website consumes the web API subset.
A command-line interface for the user to interact with the system. The CLI consumes the core API subset.
This section describes our implementation of the architechture described above.
- The networking protocol chosen for communication between all clients and servers is HTTP.
- The programming language chosen for the backend applications and the CLI is Golang.
- The relational DBMS chosen is PostgreSQL.
- Redis will be used as cache and message broker.
- AWS S3 can be used as production file storage. For small scale environments we provide an implementation of an S3-API-compliant HTTP server in Golang.
- The website should be built with the fanciest technology of the moment.
TODO.
This section describes all kinds of configurations for each system component.
TODO: Describe build time configuration files, database and cache stored settings, environment variables...
TODO.
TODO.