Skip to content

Commit

Permalink
Merge branch 'main' into KevinJBoyer-patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinJBoyer authored Apr 26, 2024
2 parents e8414d2 + 5730b46 commit f1ca5d3
Show file tree
Hide file tree
Showing 12 changed files with 191 additions and 39 deletions.
3 changes: 3 additions & 0 deletions app/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ build:
start:
docker compose up --detach

start-debug:
docker compose -f ../docker-compose.yml -f ../docker-compose.debug.yml up --detach

run-logs: start
docker compose logs --follow --no-color $(APP_NAME)

Expand Down
57 changes: 54 additions & 3 deletions app/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions app/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pytest-watch = "^4.2.0"
pytest-lazy-fixture = "^0.6.3"
types-pyyaml = "^6.0.12.11"
setuptools = "^68.2.2"
debugpy = "^1.8.1"

[build-system]
requires = ["poetry-core>=1.0.0"]
Expand Down
26 changes: 26 additions & 0 deletions docker-compose.debug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: "3.8"

# run with `docker compose -f`
# combines ports and env vars with the main docker-compose.yml main-app service

services:
main-app:
build:
context: ./app
target: dev
args:
- RUN_UID=${RUN_UID:-4000}
- RUN_USER=${RUN_USER:-app}
container_name: main-app
env_file: ./app/local.env
command: [
"poetry", "run", "python", "-m", "debugpy",
"--listen", "0.0.0.0:5678",
"--wait-for-client", "--log-to-stderr",
"-m", "flask", "--app", "src.app", "run",
"--host", "0.0.0.0", "--port", "8080", "--no-reload"
]
ports:
- 5678:5678
volumes:
- ./app:/app
51 changes: 50 additions & 1 deletion docs/app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ root
│ └── src
│ └── auth Authentication code for API
│ └── db
│ └── models DB model definitions
│ └── models DB model definitions
│ └── migrations DB migration configs
│ └── versions The DB migrations
│ └── logging
Expand Down Expand Up @@ -105,3 +105,52 @@ Any environment variables specified directly in the [docker-compose](/docker-com
## Authentication

This API uses a very simple [ApiKey authentication approach](https://apiflask.com/authentication/#use-external-authentication-library) which requires the caller to provide a static key. This is specified with the `API_AUTH_TOKEN` environment variable.

## VSCode Remote Attach Container Debugging

The API can be run in debug mode that allows for remote attach debugging (currently only supported from VSCode) to the container.

- Requirements:

- VSCode Python extension
- Updated Poetry with the `debugpy` dev package in `pyproject.toml`

- First create a file `./vscode/launch.json` - as shown below. (Default name of `Python: Remote Attach`)

- Start the server in debug mode via `make start-debug` or `make start-debug run-logs`.
- This will start the `main-app` service with port 5678 exposed.

- The server will start in waiting mode, waiting for you to attach the debugger (see `/src/app.py`) before continuing to run.

- Go to your VSCode debugger window and run the `Python: Remote Attach` option

- You should now be able to hit set breakpoints throughout the API

`./vscode/launch.json`:

```
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Remote Attach",
"type": "debugpy",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
},
"pathMappings": [
{
"localRoot": "${workspaceFolder}/app",
"remoteRoot": "."
}
],
"justMyCode": false,
}
]
}
```
24 changes: 1 addition & 23 deletions docs/app/api-details.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,6 @@ See [Technical Overview](./technical-overview.md) for details on the technologie

Each endpoint is configured in the [openapi.generated.yml](/app/openapi.generated.yml) file which provides basic request validation. Each endpoint specifies an `operationId` that maps to a function defined in the code that will handle the request.

To make handling a request easier, an [ApiContext](/app/src/util/api_context.py) exists which will fetch the DB session, request body, and current user. This can be used like so:
```py
def example_post() -> flask.Response:
with api_context_manager() as api_context:
# Work with the request body
first_name = api_context.request_body["first_name"]

# Work with the user
current_user = api_context.current_user

# Work with the DB session
api_context.db_session.query(..)

# Return a response
return response_util.success_response(
message="Success",
data={"db_model_id": "1234"}, # Whatever the response object should be
status_code=201
)
```
For more complex usages, it is recommended you put the implementation into a separate handler file in order to keep the API entrypoints easier to read.

# Swagger

The Swagger UI can be reached locally at [http://localhost:8080/docs](http://localhost:8080/docs) when running the API. The UI is based on the [openapi.generated.yml](/app/openapi.generated.yml) file.
Expand All @@ -39,7 +17,7 @@ All model schemas defined can be found at the bottom of the UI.
# Routes

## Health Check
[GET /v1/healthcheck](/app/src/route/healthcheck.py) is an endpoint for checking the health of the service. It verifies that the database is reachable, and that the API service itself is up and running.
[GET /v1/healthcheck](/app/src/api/healthcheck.py) is an endpoint for checking the health of the service. It verifies that the database is reachable, and that the API service itself is up and running.

Note this endpoint explicitly does not require authorization so it can be integrated with any automated monitoring you may build.

Expand Down
2 changes: 1 addition & 1 deletion docs/app/database/database-access-management.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This document describes the best practices and patterns for how the application

## Client Initialization and Configuration

The database client is initialized when the application starts (see [src/\_\_main\_\_.py](../../../app/src/app.py). The database engine that is used to create acquire connections to the database is initialized using the database configuration defined in [db_config.py](../../../app/src/db/db_config.py), which is configured through environment variables. The initialized database client is then stored on the Flask app's [\`extensions\` dictionary](https://flask.palletsprojects.com/en/2.2.x/src/#flask.Flask.extensions) to be used throughout the lifetime of the application.
The database client is initialized when the application starts (see [`src/__main__.py`](../../../app/src/app.py)). The database engine that is used to acquire connections to the database is initialized using the database configuration defined in [postgres_config.py](../../../app/src/adapters/db/clients/postgres_config.py), which is configured through environment variables. The initialized database client is then stored on the Flask app's [`extensions` dictionary](https://flask.palletsprojects.com/en/2.2.x/extensions/) to be used throughout the lifetime of the application.

## Session Management

Expand Down
Loading

0 comments on commit f1ca5d3

Please sign in to comment.