diff --git a/apps/trading-service/README.md b/apps/trading-service/README.md new file mode 100644 index 00000000..558c5120 --- /dev/null +++ b/apps/trading-service/README.md @@ -0,0 +1,57 @@ +# AITBC Trading Service + +Manages trading operations. + +## Installation + +```bash +cd /opt/aitbc +poetry install --with trading-service +``` + +## Database Setup + +Create a separate database for the trading service: + +```sql +CREATE DATABASE aitbc_trading; +CREATE USER aitbc_trading WITH PASSWORD 'password'; +GRANT ALL PRIVILEGES ON DATABASE aitbc_trading TO aitbc_trading; +``` + +## Running + +```bash +# Development +python -m trading_service.main + +# Production (systemd) +sudo systemctl start trading-service +sudo systemctl enable trading-service +``` + +## Endpoints + +- `GET /health` - Health check +- `GET /trading/status` - Get trading status + +## Migration Status + +**Foundation Created:** +- Application structure (pyproject.toml, main.py) +- Systemd service configuration +- Basic health and status endpoints + +**Remaining:** +- Extract trading domain models from coordinator-api +- Extract trading services from coordinator-api +- Extract trading routers from coordinator-api +- Setup separate database session management +- Update coordinator-api to remove trading code +- End-to-end testing with gateway + +## Service Configuration + +- Port: 8104 +- Database: aitbc_trading +- Gateway route: /trading/* diff --git a/apps/trading-service/pyproject.toml b/apps/trading-service/pyproject.toml new file mode 100644 index 00000000..bb68818e --- /dev/null +++ b/apps/trading-service/pyproject.toml @@ -0,0 +1,24 @@ +[project] +name = "trading-service" +version = "0.1.0" +description = "AITBC Trading Service for trading operations" +authors = [ + {name = "AITBC Team", email = "team@aitbc.dev"} +] +requires-python = ">=3.13" +dependencies = [ + "fastapi>=0.104.0", + "uvicorn>=0.24.0", + "sqlmodel>=0.0.14", + "asyncpg>=0.30.0", + "aitbc-core", +] + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +packages = [ + { include = "trading_service", from = "src" } +] diff --git a/apps/trading-service/src/trading_service/__init__.py b/apps/trading-service/src/trading_service/__init__.py new file mode 100644 index 00000000..e8322521 --- /dev/null +++ b/apps/trading-service/src/trading_service/__init__.py @@ -0,0 +1,6 @@ +""" +AITBC Trading Service +Manages trading operations +""" + +__version__ = "0.1.0" diff --git a/apps/trading-service/src/trading_service/main.py b/apps/trading-service/src/trading_service/main.py new file mode 100644 index 00000000..932071c5 --- /dev/null +++ b/apps/trading-service/src/trading_service/main.py @@ -0,0 +1,72 @@ +""" +Trading Service main application +Manages trading operations +""" + +from contextlib import asynccontextmanager +from typing import AsyncIterator + +from fastapi import FastAPI +from pydantic import BaseModel + +from aitbc import ( + configure_logging, + get_logger, + RequestIDMiddleware, + PerformanceLoggingMiddleware, + RequestValidationMiddleware, + ErrorHandlerMiddleware, +) + +# Configure structured logging +configure_logging(level="INFO") +logger = get_logger(__name__) + + +@asynccontextmanager +async def lifespan(app: FastAPI) -> AsyncIterator[None]: + """Lifecycle events for the Trading Service.""" + logger.info("Starting Trading Service") + yield + logger.info("Shutting down Trading Service") + + +app = FastAPI( + title="AITBC Trading Service", + description="Manages trading operations", + version="0.1.0", + lifespan=lifespan, +) + +# Add middleware +app.add_middleware(RequestIDMiddleware) +app.add_middleware(PerformanceLoggingMiddleware) +app.add_middleware(RequestValidationMiddleware, max_request_size=10*1024*1024) +app.add_middleware(ErrorHandlerMiddleware) + + +class HealthResponse(BaseModel): + """Health check response""" + status: str + service: str + + +@app.get("/health") +async def health() -> HealthResponse: + """Health check endpoint""" + return HealthResponse(status="healthy", service="trading-service") + + +@app.get("/trading/status") +async def trading_status() -> dict[str, str]: + """Get trading status""" + return { + "status": "operational", + "service": "trading-service", + "message": "Trading service is running", + } + + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8104) diff --git a/apps/trading-service/trading-service.service b/apps/trading-service/trading-service.service new file mode 100644 index 00000000..78d6cd48 --- /dev/null +++ b/apps/trading-service/trading-service.service @@ -0,0 +1,17 @@ +[Unit] +Description=AITBC Trading Service +After=network.target postgresql.service + +[Service] +Type=simple +User=aitbc +WorkingDirectory=/opt/aitbc/apps/trading-service +Environment="PATH=/opt/aitbc/venv/bin" +Environment="PYTHONPATH=/opt/aitbc/packages/py/aitbc-core/src:/opt/aitbc/apps/trading-service/src:/opt/aitbc" +Environment="DATABASE_URL=postgresql+asyncpg://aitbc_trading:password@localhost:5432/aitbc_trading" +ExecStart=/opt/aitbc/venv/bin/python -m trading_service.main +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target