Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Architecture Overview

The entire Architecture contains an API server to serve an openapi gateway, as well as a Task server in charge of workload execution

  • A Redis server exists in order to sync and manage state between the API and the Task servers

Architecture Overview

Components

API Server

A fastAPI application serving 2 endpoints, one for task workload creation and another for fetching the state of the task (including result if the task executed sccessfully)

Task Server

A celery application for handling async/concurrent task workloads, as well as assuring stable execution in case of errors/outages

State Server

A redis server used to sync between the API server requests, and the Task server execution states

  • this is used solely for task orchestration, as the main concern is allowing only non-blocking operations

Codebase

For the purpose of the exercise all the codebase is stored in a single repository - however, for all intents an purposes each server codebase is structured to work in a repository of their own

  • There is an interesting discussion to be had here, as it affects many aspects of the codebase structure

Dependencies

Run dependencies and dev dependencies are split as to not contaminate environments. In a devcontaianer they are essentially merged together to include all dependencies needed for development as well, while in production only the run dependencies are used.

Development

The development environment is mainly tailored to work for vscode out-of-the-box, however dropping in pyCharm or any other IDE which supports devcontainers should require minimal effort.

  • All files and configurations regarding the development environment are located inside the .devcontainer folder

Taking the codebase considertaion into account, each server has a seperate developer environment set up, having the main code container attachable by the IDE

Getting Started

  1. clone the repository locally
  2. open the folder for a desired development project (api/server) in vscode
  3. CTRL+SHIFT+P to open up the command pallet and choose Rebuild/Reopen in Container (first time will only have a Reopen option)

Configuration

All configurations values are stored in yaml format under the config directory. Configurations can be accessed via their respective pydantic models for validations

  • Provided config.yml files are intended for development/ci, for production those files can be replaced with production values
  • My personal preference is to steer away from environment variables as much as possible, for security and consistency mainly

Running / Debugging

Each server's development environment spins up the other server and the redis sync in docker compose, however the main server in each project is not auto started for easier development cycle.

  • All components in the compose stack, beside the devcontainer, are built in the same manner as in production, to better simulate staging issues

The main entry point for each server is the main.py file in the root folder.

  • Not necessary, as the same result is achievable through the docker entrypoint, however it is easier to follow when developing, and provides a unified interface

Either use the vscode configured launch configuration Vscode Debug

or execute the following command in the terminal, at the root of the project

python main.py
  • when executing directly in the terminal, debugpy should be used for debugging (already set up in the Debug launch configuration in vscode)
  • Debug mode has auto reload on file changes for easier development cycles
  • all debugger features are applicable

Documentation

In general I am for principles of clean code (as much as it doesnt detract from development) and prefer that the code be self explanatory rather than include line comments.

That being said, functionality is documented and integrated in intellisense.

Additionally, there is an openapi documentation site being spun up alongside the API server, accessible at http://localhost:8000/docs

  • can execute queries in the api from the docs directly for easier development

Testing

Tests are split into unit tests and integration tests (test files ending with integration).

Running all tests alongside coverage can be easily done via the Testing panel in vscode Vscode Testing Panel

After the first successful run of the test suite with coverage, indicators will be added denoting each file/branch and line coverage in editor Vscode Test Coverage

or run via the command line:

pytest # run test suite
pytest --cov=. tests/ # run test suite with coverage
  • Running from the terminal however, will not show up in the ui integration in vscode

Caveats / Notes

QASM code for testing

I used the following code for testing the workflow:

OPENQASM 3.0; 

include "stdgates.inc"; 
bit[2] c; 
qubit[2] q; 
h q[0]; 
cx q[0], q[1]; 
c[0] = measure q[0]; 
c[1] = measure q[1];

Git Issues in current workspace

For ease of use I have created a single repo in git, which causes the git functionality to detach when inside the dev containers - as they are not seeing the .git folder in the root of the repo.

Normally each project will be in it's own repo - circumventing the issue entirely.

Use case not covered

The task not found use case in the instructions is not covered, as it requires a more comprehensive architecture for managing the application scope.

It is not included due to time constraints, however would love to delve deeper into what it means (it may sound like overkill at first, but there are long term considerations)

HTTP/HTTPS

Currently everything is set up to work over http, since i did not want to waste time on self-signed SSL certificates. Naturally in production Authoratively signed certificates will be in place, either via proxying the connection or it can be configured internally when needed.

Shared Core Functionality

As you may notice, there are several core functionalities that can be reused between the projects. In a multi repo setup, I would aim for creating a dedicated repo for the core functionality libraries, and submodule them upstream to where they are needed.

Depenency Injection

Depenency injection is not really included in the project, as I was not sure if it is outside the scope, however I usually lean towards implementing it for bigger projects as it helps maintainability/reusability as well as simplifies testing.

Logging

All logs are currently output to stdout so they can later be collected by any indexing service.

  • for production purpose I would lean towards having log entries written to files for better consistency in the machine lifecycle

Out of Date Example in Instructions

qc.measure() in the example provided is no longer the proper format, if you wish to update the task, then you can replace it with the following line:

qc.measure([0,1], [0,1])

Extensions

Some extensions for vscode are bundled with the devcontainer for quality-of-life and alignment between developers, as follows:

  1. cweijan.vscode-redis-client - Redis client in IDE (for debugging state)
  2. charliermarsh.ruff - Python Linter and formatter (rules are preconfigured in the root)
  3. usernamehw.errorlens - Inline errors in the code editor

Component Devlopment lifecycles

A limitation exists in the current setup, which prevents any tracking of changes in the docker compose stack/images, and needs to have the entire updated codebase for all, as well as a rebuild

In a proper setup, the docker images will be built by ci and published to a repository - which the development compose stack should pull instead of building all the components "from source"

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages