From e15477dc55a6a052ee42adee3f306a9d32dc8e22 Mon Sep 17 00:00:00 2001 From: aitbc Date: Thu, 30 Apr 2026 11:26:46 +0200 Subject: [PATCH] Create marketplace-service foundation - Created marketplace-service application structure - Added pyproject.toml with FastAPI, SQLModel, asyncpg, and aitbc-core dependencies - Implemented main.py with basic marketplace service structure - Created systemd service file for marketplace-service (port 8102) - Added README.md with installation and configuration instructions This starts Phase 4.4: Extract Marketplace Service (foundation created) --- apps/marketplace-service/README.md | 57 +++++++++++++++ .../marketplace-service.service | 17 +++++ apps/marketplace-service/pyproject.toml | 24 +++++++ .../src/marketplace_service/__init__.py | 6 ++ .../src/marketplace_service/main.py | 72 +++++++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 apps/marketplace-service/README.md create mode 100644 apps/marketplace-service/marketplace-service.service create mode 100644 apps/marketplace-service/pyproject.toml create mode 100644 apps/marketplace-service/src/marketplace_service/__init__.py create mode 100644 apps/marketplace-service/src/marketplace_service/main.py diff --git a/apps/marketplace-service/README.md b/apps/marketplace-service/README.md new file mode 100644 index 00000000..8b3c5439 --- /dev/null +++ b/apps/marketplace-service/README.md @@ -0,0 +1,57 @@ +# AITBC Marketplace Service + +Manages GPU marketplace operations. + +## Installation + +```bash +cd /opt/aitbc +poetry install --with marketplace-service +``` + +## Database Setup + +Create a separate database for the marketplace service: + +```sql +CREATE DATABASE aitbc_marketplace; +CREATE USER aitbc_marketplace WITH PASSWORD 'password'; +GRANT ALL PRIVILEGES ON DATABASE aitbc_marketplace TO aitbc_marketplace; +``` + +## Running + +```bash +# Development +python -m marketplace_service.main + +# Production (systemd) +sudo systemctl start marketplace-service +sudo systemctl enable marketplace-service +``` + +## Endpoints + +- `GET /health` - Health check +- `GET /marketplace/status` - Get marketplace status + +## Migration Status + +**Foundation Created:** +- Application structure (pyproject.toml, main.py) +- Systemd service configuration +- Basic health and status endpoints + +**Remaining:** +- Extract marketplace domain models from coordinator-api +- Extract marketplace services from coordinator-api +- Extract marketplace routers from coordinator-api +- Setup separate database session management +- Update coordinator-api to remove marketplace code +- End-to-end testing with gateway + +## Service Configuration + +- Port: 8102 +- Database: aitbc_marketplace +- Gateway route: /marketplace/* diff --git a/apps/marketplace-service/marketplace-service.service b/apps/marketplace-service/marketplace-service.service new file mode 100644 index 00000000..6e64005f --- /dev/null +++ b/apps/marketplace-service/marketplace-service.service @@ -0,0 +1,17 @@ +[Unit] +Description=AITBC Marketplace Service +After=network.target postgresql.service + +[Service] +Type=simple +User=aitbc +WorkingDirectory=/opt/aitbc/apps/marketplace-service +Environment="PATH=/opt/aitbc/venv/bin" +Environment="PYTHONPATH=/opt/aitbc/packages/py/aitbc-core/src:/opt/aitbc/apps/marketplace-service/src:/opt/aitbc" +Environment="DATABASE_URL=postgresql+asyncpg://aitbc_marketplace:password@localhost:5432/aitbc_marketplace" +ExecStart=/opt/aitbc/venv/bin/python -m marketplace_service.main +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target diff --git a/apps/marketplace-service/pyproject.toml b/apps/marketplace-service/pyproject.toml new file mode 100644 index 00000000..0dddfdfc --- /dev/null +++ b/apps/marketplace-service/pyproject.toml @@ -0,0 +1,24 @@ +[project] +name = "marketplace-service" +version = "0.1.0" +description = "AITBC Marketplace Service for GPU marketplace 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 = "marketplace_service", from = "src" } +] diff --git a/apps/marketplace-service/src/marketplace_service/__init__.py b/apps/marketplace-service/src/marketplace_service/__init__.py new file mode 100644 index 00000000..aec04833 --- /dev/null +++ b/apps/marketplace-service/src/marketplace_service/__init__.py @@ -0,0 +1,6 @@ +""" +AITBC Marketplace Service +Manages GPU marketplace operations +""" + +__version__ = "0.1.0" diff --git a/apps/marketplace-service/src/marketplace_service/main.py b/apps/marketplace-service/src/marketplace_service/main.py new file mode 100644 index 00000000..33987dc7 --- /dev/null +++ b/apps/marketplace-service/src/marketplace_service/main.py @@ -0,0 +1,72 @@ +""" +Marketplace Service main application +Manages GPU marketplace 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 Marketplace Service.""" + logger.info("Starting Marketplace Service") + yield + logger.info("Shutting down Marketplace Service") + + +app = FastAPI( + title="AITBC Marketplace Service", + description="Manages GPU marketplace 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="marketplace-service") + + +@app.get("/marketplace/status") +async def marketplace_status() -> dict[str, str]: + """Get marketplace status""" + return { + "status": "operational", + "service": "marketplace-service", + "message": "Marketplace service is running", + } + + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8102)