diff --git a/.env.example b/.env.example index cdf42386..47449498 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ ENV = "DVP" DATABASE_URL = "mysql+aiomysql://root:root_bot_buster@localhost/playerdata" -KAFKA_HOST = "kafka:9092" \ No newline at end of file +KAFKA_HOST = "kafka:9092" +POOL_RECYCLE = 60 +POOL_TIMEOUT = 30 \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..2a8d0508 --- /dev/null +++ b/Makefile @@ -0,0 +1,87 @@ +.PHONY: clean clean-test clean-pyc clean-build build help +.DEFAULT_GOAL := help + +define PRINT_HELP_PYSCRIPT +import re, sys + +for line in sys.stdin: + match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) + if match: + target, help = match.groups() + print("%-20s %s" % (target, help)) +endef +export PRINT_HELP_PYSCRIPT + +help: + @python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) + +clean-pyc: ## clean python cache files + find . -name '*.pyc' -exec rm -f {} + + find . -name '*.pyo' -exec rm -f {} + + find . -name '*~' -exec rm -f {} + + find . -name '__pycache__' -exec rm -fr {} + + find . -name '.pytest_cache' -exec rm -fr {} + + +clean-test: ## cleanup pytests leftovers + rm -f .coverage + rm -fr htmlcov/ + rm -fr test_results/ + rm -f *report.html + rm -f log.html + rm -f test-results.html + rm -f output.xml + +test: clean ## Run pytest unit tests + python3 -m pytest + +test-debug: ## Run unit tests with debugging enabled + python3 -m pytest --pdb + +test-coverage: clean ## Run unit tests and check code coverage + PYTHONPATH=src python3 -m pytest --cov=src tests/ --disable-warnings + +docker-up: ## Startup docker + docker-compose --verbose up + +docker-build: ## Startup docker + docker-compose --verbose up --build + +setup: requirements pre-commit-setup docker-build test-setup api-setup ## setup & run after downloaded repo + +pre-commit-setup: ## Install pre-commit + python3 -m pip install pre-commit + pre-commit --version + +pre-commit: ## Run pre-commit + pre-commit run --all-files + +test-setup: + python3 -m pip install pytest + +requirements: + python3 -m pip install -r requirements.txt + +docker-down: + docker-compose down + +docker-rebuild: docker-down + docker-compose --verbose up --build + +docker-force-rebuild: + docker-compose --verbose up --build --force-recreate + +api-setup: + python3 -m pip install "fastapi[all]" + +env-setup: + touch .env + echo "KAFKA_HOST= 'localhost:9092'" >> .env + echo "DATABASE_URL= 'mysql+aiomysql://root:root_bot_buster@localhost:3306/playerdata'" >> .env + echo "ENV='DEV'" >> .env + echo "POOL_RECYCLE='60'" >> .env + echo "POOL_TIMEOUT='30'" >> .env + +docs: + open http://localhost:5000/docs + xdg-open http://localhost:5000/docs + . http://localhost:5000/docs \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml index 8f9f7885..ac588120 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -84,7 +84,9 @@ services: environment: - KAFKA_HOST=kafka:9092 - DATABASE_URL=mysql+aiomysql://root:root_bot_buster@mysql:3306/playerdata - - env=DEV + - ENV=DEV + - POOL_RECYCLE=60 + - POOL_TIMEOUT=30 # env_file: # - .env depends_on: diff --git a/src/core/config.py b/src/core/config.py index 3dc84744..0e484ebb 100644 --- a/src/core/config.py +++ b/src/core/config.py @@ -4,7 +4,9 @@ class Settings(BaseSettings): ENV: str DATABASE_URL: str - KAFKA_HOST: str = "localhost:9094" + KAFKA_HOST: str + POOL_RECYCLE: int + POOL_TIMEOUT: int settings = Settings() diff --git a/src/core/database/database.py b/src/core/database/database.py index cd9d1235..4ff4937c 100644 --- a/src/core/database/database.py +++ b/src/core/database/database.py @@ -6,8 +6,12 @@ from src.core.config import settings # Create an async SQLAlchemy engine -engine = create_async_engine(settings.DATABASE_URL, echo=(settings.ENV != "PRD")) - +engine = create_async_engine( + settings.DATABASE_URL, + pool_timeout=settings.POOL_TIMEOUT, + pool_recycle=settings.POOL_RECYCLE, + echo=(settings.ENV != "PRD"), +) # Create a session factory SessionFactory = sessionmaker( bind=engine, diff --git a/tests/test_player_api.py b/tests/test_player_api.py new file mode 100644 index 00000000..e106aa27 --- /dev/null +++ b/tests/test_player_api.py @@ -0,0 +1,30 @@ +import os +import sys +import requests +from unittest import TestCase + + +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + +class TestPlayerAPI(TestCase): + + def testValidPlayerReturns200(self): + url = "http://localhost:5000/v2/players/score" + params = {"name": ["Player1"]} + score = requests.get(url, params) + assert score.status_code == 200 + + def testInvalidPlayerReturns200(self): + url = "http://localhost:5000/v2/players/score" + params = {"name": [""]} + response = requests.get(url, params) + assert response.status_code == 200 + + def testInvalidPlayerBodyIsEmpty(self): + url = "http://localhost:5000/v2/players/score" + params = {"name": [""]} + response = requests.get(url, params) + error = f"Invalid response return type, expected list[dict]" + print(response.json()) + assert isinstance(response.json(), list), error \ No newline at end of file