Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker/Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ COPY . .
EXPOSE 8000

# Run the application with reload for development
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
2 changes: 1 addition & 1 deletion docker/Dockerfile.prod
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ COPY . .
EXPOSE 8000

# Run the application
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
26 changes: 26 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
services:
rabbitmq:
image: rabbitmq:3.12-management-alpine
container_name: rabbitmq
ports:
- "5672:5672" # AMQP port
- "15672:15672" # Management UI port
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
volumes:
- rabbitmq_data:/var/lib/rabbitmq
restart: unless-stopped
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s

api:
build:
context: ..
Expand All @@ -10,10 +29,17 @@ services:
- ..:/app
environment:
- PYTHONUNBUFFERED=1
- CELERY_BROKER_URL=amqp://guest:guest@rabbitmq:5672//
depends_on:
rabbitmq:
condition: service_healthy
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s

volumes:
rabbitmq_data:
23 changes: 0 additions & 23 deletions main.py

This file was deleted.

2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
fastapi==0.104.1
uvicorn[standard]==0.24.0
python-multipart==0.0.6
celery==5.3.4
kombu==5.3.4
1 change: 1 addition & 0 deletions src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# FastAPI application package
28 changes: 28 additions & 0 deletions src/celery_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import os

from celery import Celery

# RabbitMQ connection URL
broker_url = os.getenv("CELERY_BROKER_URL")
# RPC backend for results (uses RabbitMQ RPC, no additional service needed)
result_backend = os.getenv("CELERY_RESULT_BACKEND")

# Create Celery instance
celery_app = Celery(
"fastapi_app",
broker=broker_url,
backend=result_backend,
include=["src.tasks"],
)

# Celery configuration
celery_app.conf.update(
task_serializer="json",
accept_content=["json"],
result_serializer="json",
timezone="UTC",
enable_utc=True,
task_track_started=True,
task_time_limit=30 * 60,
task_soft_time_limit=25 * 60,
)
47 changes: 47 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

from src.tasks import process_message

app = FastAPI(title="FastAPI Starter", description="A starter FastAPI application", version="1.0.0")

# CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)


class MessageRequest(BaseModel):
message: str


@app.get("/")
async def root():
return {"message": "Hello World", "status": "ok"}


@app.get("/health")
async def health():
return {"status": "healthy"}


@app.post("/send-task")
async def send_task(request: MessageRequest):
"""
Endpoint do wysyłania zadań do kolejki RabbitMQ przez Celery.
"""
try:
task = process_message.delay(request.message)
return {
"status": "success",
"message": "Task sent to queue",
"task_id": task.id,
"message_content": request.message,
}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to send task: {str(e)}") from e
18 changes: 18 additions & 0 deletions src/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from datetime import datetime

from src.celery_app import celery_app


@celery_app.task(name="tasks.process_message")
def process_message(message: str) -> dict:
"""
Przykładowe zadanie Celery, które przetwarza wiadomość.
W rzeczywistej aplikacji tutaj można wykonać ciężkie operacje.
"""
# Symulacja przetwarzania
result = {
"status": "processed",
"message": message,
"processed_at": datetime.utcnow().isoformat() + "Z",
}
return result
2 changes: 1 addition & 1 deletion tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import pytest
from fastapi.testclient import TestClient

from main import app
from src.main import app


@pytest.fixture
Expand Down