Skip to content

Commit

Permalink
Merge pull request #42 from wednesday-solutions/feat/readme-updated-a…
Browse files Browse the repository at this point in the history
…nd-other-validations

Readme file updated along with other validations
  • Loading branch information
shamoilattaar-wednesday authored Apr 18, 2024
2 parents cf64071 + 452a65c commit f1453be
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 181 deletions.
22 changes: 11 additions & 11 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
SECRET_KEY=your_secret_key
# Database Configuration
DB_NAME=
DB_HOSTNAME=localhost
DB_PORT=3306
DB_USERNAME=
DB_PASSWORD=
DB_HOSTNAME=
DB_PORT=
DB_NAME=
SECRET_KEY=
REDIS_URL=
DB_ROOT_PASSWORD=
# Additional Configuration
REDIS_URL=redis://localhost:6379/
SENTRY_DSN=
SLACK_WEBHOOK_URL=
ENVIRONMENT_NAME=
DB_ROOT_PASSWORD= //this is applicable for .env.local file only
// you will get these data from signoz portal
# Advance Usage - Signoz Configuration
OTEL_RESOURCE_ATTRIBUTES=
OTEL_EXPORTER_OTLP_ENDPOINT=
OTEL_EXPORTER_OTLP_HEADERS=
OTEL_EXPORTER_OTLP_PROTOCOL=
CACHE_ENABLED=
SENTRY_ENABLED=
SLACK_ENABLED=
# Docker Configuration
ENVIRONMENT_NAME=
133 changes: 90 additions & 43 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,20 @@ This repository provides a template for creating and deploying a FastAPI project

- [Features](#features)
- [Getting started](#getting-started)
- [Initialize & Setup Environment](#1-initialize--setup-environment)
- [Variables Configuration](#2-variables-configuration)
- [Database Migrations](#3-database-migrations)
- [Redis Dependency & Installation](#4-redis-dependency)
- [Celery Dependency](#5-celery-dependency)
- [Run the Project](#6-run-the-project)
- [Advanced Usage](#advanced-usage)
- [Circuit breakers](#circuit-breakers)
- [Configuring Signoz Monitoring Tool](#configuring-signoz-monitoring-tool)
- [Logging with Signoz](#logging-with-signoz)
- [Database Monitoring Using Percona](#database-monitoring-using-percona)
- [Deploy Service on AWS ECS](#deploy-service-on-aws-ecs)
- [Related Dashboard Links](#related-dashboard-links)
- [Additional Useful scripts](#additional-useful-scripts)

### Features

Expand Down Expand Up @@ -38,23 +51,42 @@ This repository provides a template for creating and deploying a FastAPI project
- Docker
- mysql

#### 1. Initialize Local Environment
#### 1. Initialize & Setup Environment

- To set up your local environment, run the following script:
- To initialize and set up your environment, run the following script:

```
./scripts/initialize-env.sh
```

This script installs the necessary dependencies and prepares the environment for running the FastAPI application on your local machine.
This script installs the necessary dependencies and prepares the environment for running the FastAPI application on your machine.

Create a .env.local file with reference of .env.example
Run following command to inject env file
```shell
set -a source .env.local set +a
```
##### Activate the environment
```
# Mac & Linux:
source ./venv/bin/activate
# Windows
.\venv\scripts\activate
```

#### 2. Variables Configuration
Update database environment variables in your .env.local file:
```
DB_NAME=
DB_HOSTNAME=localhost
DB_PORT=3306
DB_USERNAME=
DB_PASSWORD=
```
Additional Configuration (Optional):
```
SENTRY_DSN=
SLACK_WEBHOOK_URL=
DB_ROOT_PASSWORD=
```

#### 2. Database Migrations
#### 3. Database Migrations
Create new database migrations when you make changes to your models. Use the following command:
```
alembic revision -m 'brief description of changes'
Expand All @@ -68,24 +100,40 @@ alembic upgrade head
```
This command updates the database schema to reflect the latest changes defined in the migration scripts

#### 3. Redis Dependency
#### 4. Redis Dependency
##### Install Locally:
```
docker run --name recorder-redis -p 6379:6379 -d redis:alpine
# Mac
brew install redis
brew services start redis
# Windows
Please refer: https://developer.redis.com/create/windows/
# Linux
sudo apt install redis
sudo systemctl enable redis
sudo systemctl start redis
sudo systemctl status redis # verify status
```
or add the REDIS_URL in .env.local file

##### Install via docker:
```
docker run --name recorder-redis -p 6379:6379 -d redis:alpine
```

#### 4. Celery Dependency
- Run following command to initiallize the celery worker
```shell
celery -A app.app.celery worker -l info
```
- Turn Up Celery Flower with
```shell
flower --broker=${REDIS_URL}/6 --port=5555
```
#### 5. Celery Dependency
Run following command to initiallize the celery worker
```
celery -A app.app.celery worker -l info
```
[Optional] Turn Up Celery Flower with
```
flower --broker=${REDIS_URL}/6 --port=5555
```

#### 5. Run the Project
#### 6. Run the Project

##### Running Application Locally

Expand All @@ -106,23 +154,9 @@ This script upgrades the database migrations using Alembic and starts the FastAP
docker compose --env-file .env.docker up
```

### Advanced Usage

#### 6. Deploy Service on AWS ECS
To deploy the FastAPI application on AWS ECS, use the following script:

```
./scripts/setup-ecs.sh develop
```

The setup-ecs.sh script leverages AWS Copilot to deploy the service. Provide the environment name as an argument (e.g., develop). The script creates and deploys an environment, then deploys the FastAPI service on that environment.

Note: Ensure you have AWS credentials configured and AWS Copilot installed for successful deployment.

#### New to AWS Copilot?
If you are new to AWS Copilot or you want to learn more about AWS Copilot, please refer to [this helpful article](https://www.wednesday.is/writing-tutorials/how-to-use-copilot-to-deploy-projects-on-ecs) that guides you through the process of setting up AWS Copilot locally as well as also helps you understand how you can publish and update an application using 4 simple steps.


#### 7. Circuit breakers
#### Circuit breakers

Using the Circuit Breaker for External API Calls

Expand All @@ -147,9 +181,7 @@ async def external_service_endpoint():
raise HTTPException(status_code=503, detail="Service temporarily unavailable")
```
### Advanced Usage

#### Using Signoz Monitoring Tool
#### Configuring Signoz Monitoring Tool
To utilize Signoz for monitoring your applications, follow these steps:
Expand Down Expand Up @@ -236,14 +268,29 @@ To monitor your database using Percona, follow these steps:
By following these steps, you'll successfully configure Percona to monitor your MySQL database.

#### Dashboard Links
#### Deploy Service on AWS ECS
To deploy the FastAPI application on AWS ECS, use the following script:

```
./scripts/setup-ecs.sh develop
```
The setup-ecs.sh script leverages AWS Copilot to deploy the service. Provide the environment name as an argument (e.g., develop). The script creates and deploys an environment, then deploys the FastAPI service on that environment.
Note: Ensure you have AWS credentials configured and AWS Copilot installed for successful deployment.
#### New to AWS Copilot?
If you are new to AWS Copilot or you want to learn more about AWS Copilot, please refer to [this helpful article](https://www.wednesday.is/writing-tutorials/how-to-use-copilot-to-deploy-projects-on-ecs) that guides you through the process of setting up AWS Copilot locally as well as also helps you understand how you can publish and update an application using 4 simple steps.
#### Related Dashboard Links
- Percona: https://localhost:443
- Flower: http://localhost:5556
- Locust UI: http://localhost:8089
- Swagger UI: http://localhost:8000
#### Useful scripts
#### Additional Useful scripts
- Tests - scripts/run_tests.sh
- Linting & Formatting - scripts/lint_and_format.sh
- Load tests - scripts/load_tests.sh (Change [locust.conf](https://docs.locust.io/en/stable/configuration.html) accordinly)
7 changes: 5 additions & 2 deletions app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@


# Sentry Initialization
if settings.SENTRY_ENABLED:
if settings.SENTRY_DSN:
sentry_sdk.init(
dsn=settings.SENTRY_DSN,
traces_sample_rate=1.0, # Sample rate of 100%
)

# Check required environment variables
settings.check_environment_variables()

app = FastAPI(
title="FastAPI Template",
description="This is my first API use FastAPI",
Expand All @@ -49,7 +52,7 @@
app.add_middleware(RequestIdInjection)
app.add_middleware(CacheMiddleware, cached_endpoints=cached_endpoints.CACHED_ENDPOINTS)

if settings.SENTRY_ENABLED:
if settings.SENTRY_DSN:
try:
app.add_middleware(SentryAsgiMiddleware)
except Exception as e:
Expand Down
27 changes: 14 additions & 13 deletions app/config/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,29 @@ class DBSettings(BaseSettings):
DB_PASSWORD: str

class Config:
env_file = ".env"
env_file = ".env.local"


class FlagFeatureSettings(BaseSettings):
CACHE_ENABLED: bool
SENTRY_ENABLED: bool = False
SLACK_ENABLED: bool = False

class Config:
env_file = ".env"


class Settings(FlagFeatureSettings, DBSettings):
class Settings(DBSettings):
SECRET_KEY: str
REDIS_URL: str
SENTRY_DSN: str | None
SLACK_WEBHOOK_URL: str
SLACK_WEBHOOK_URL: str | None
ALLOWED_HOSTS: list = ["*"]
CACHE_MAX_AGE: int = 60

class Config:
env_file = ".env"
env_file = ".env.local"

def check_environment_variables(self):
if not self.DB_HOSTNAME or not self.DB_PORT or not self.DB_NAME or not self.DB_USERNAME or not self.DB_PASSWORD:
raise ValueError("Database environment variables are not set")

if not self.SECRET_KEY:
raise ValueError("SECRET_KEY is not set")

if not self.REDIS_URL:
raise ValueError("REDIS_URL is not set")


class CachedEndpoints(BaseSettings):
Expand Down
2 changes: 1 addition & 1 deletion app/routes/home/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ async def external_service_endpoint():

@home_router.get("/sentry-test", tags=["Home"])
def sentry_endpoint():
if not settings.SENTRY_ENABLED:
if not settings.SENTRY_DSN:
raise HTTPException(status_code=503, detail="Sentry is not enabled")
raise CentryTestException("Sentry Test")

Expand Down
2 changes: 1 addition & 1 deletion app/utils/slack_notification_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def send_slack_message(payload):
Returns:
HTTP response code, i.e., <Response [503]>
"""
if not settings.SLACK_ENABLEDs:
if not settings.SLACK_WEBHOOK_URL:
return

webhook_url = settings.SLACK_WEBHOOK_URL
Expand Down
28 changes: 10 additions & 18 deletions app/wrappers/cache_wrappers.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,24 @@
from __future__ import annotations

from app.config.base import settings
from app.config.redis_config import get_redis_pool


class CacheUtils:
CACHE_ENABLED = settings.CACHE_ENABLED

@classmethod
async def create_cache(cls, resp, key: str, ex: int = 60):
if cls.CACHE_ENABLED:
redis = await get_redis_pool()
await redis.set(key, resp, ex=ex)
redis = await get_redis_pool()
await redis.set(key, resp, ex=ex)

@classmethod
async def retrieve_cache(cls, key: str):
if cls.CACHE_ENABLED:
redis = await get_redis_pool()
data = await redis.get(key)
if not data:
return None, None
expire = await redis.ttl(key)
return data, expire
return None, None
redis = await get_redis_pool()
data = await redis.get(key)
if not data:
return None, None
expire = await redis.ttl(key)
return data, expire

@classmethod
async def invalidate_cache(cls, key: str):
if cls.CACHE_ENABLED:
redis = await get_redis_pool()
await redis.delete(key)
return None
redis = await get_redis_pool()
await redis.delete(key)
2 changes: 1 addition & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ services:
dockerfile: Dockerfile
command: ['celery', '-A', 'app.app.celery', 'worker', '-l', 'info']
env_file:
- .env.${ENVIRONMENT_NAME}
- .env.${ENVIRONMENT_NAME}
depends_on:
- redis
- app
Expand Down
Loading

1 comment on commit f1453be

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
app
   app.py38380%1–70
app/config
   __init__.py3167%6
   base.py38879%29–36, 54–55
   celery_config.py17170%1–27
   celery_utils.py21210%1–30
   redis_config.py5260%8–9
app/constants
   jwt_utils.py161131%11–23
app/daos
   home.py10550%11–18
   users.py726411%12–136
app/middlewares
   cache_middleware.py51510%1–67
   rate_limiter_middleware.py25250%1–35
   request_id_injection.py17170%1–25
app/models
   __init__.py330%1–5
   users.py27270%1–38
app/routes
   __init__.py12120%1–15
app/routes/cache_router
   __init__.py330%1–5
   cache_samples.py12120%1–18
app/routes/celery_router
   __init__.py330%1–5
   celery_samples.py12120%1–17
app/routes/home
   __init__.py330%1–5
   home.py33330%1–45
app/routes/users
   __init__.py330%1–5
   users.py38380%1–57
app/schemas/users
   users_request.py42420%1–73
   users_response.py10100%1–14
app/sessions
   db.py53530%1–82
app/tests
   test_basic.py201620%8–34
   test_daos_home.py231057%15–22, 28–37, 41
   test_daos_users.py1109514%19–208
app/utils
   exception_handler.py19190%1–36
   redis_utils.py440%1–7
   slack_notification_utils.py14140%1–32
   user_utils.py25250%1–36
app/wrappers
   cache_wrappers.py19190%1–24
TOTAL81871612% 

Tests Skipped Failures Errors Time
2 0 💤 0 ❌ 2 🔥 0.512s ⏱️

Please sign in to comment.