Working docker-compose.yaml added. Services start and work.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
*.so
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
.venv
|
||||
venv
|
||||
.env
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
Dockerfile
|
||||
.dockerignore
|
||||
@@ -0,0 +1,54 @@
|
||||
FROM python:3.13-slim
|
||||
|
||||
# Install FFmpeg and system dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
ffmpeg \
|
||||
ca-certificates \
|
||||
&& \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set Python environment variables
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Copy and install Python dependencies
|
||||
# ------------------------------------------------------------
|
||||
COPY web/backend/requirements-web.txt .
|
||||
RUN pip install --no-cache-dir -r requirements-web.txt
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Copy the backend application code
|
||||
# ------------------------------------------------------------
|
||||
COPY web/backend /app/backend
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Copy and install the audio_splitter package
|
||||
# ------------------------------------------------------------
|
||||
COPY audio_splitter /app/audio_splitter
|
||||
COPY setup.py pyproject.toml README.md /app/
|
||||
|
||||
# Install audio_splitter as a package
|
||||
RUN pip install --no-cache-dir /app
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Create a non-root user
|
||||
# ------------------------------------------------------------
|
||||
RUN addgroup --system --gid 1000 appgroup && \
|
||||
adduser --system --uid 1000 --ingroup appgroup appuser && \
|
||||
chown -R appuser:appgroup /app
|
||||
|
||||
USER appuser
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Expose port and start
|
||||
# ------------------------------------------------------------
|
||||
EXPOSE 8000
|
||||
|
||||
# PYTHONPATH is already /app by default because we set WORKDIR /app
|
||||
CMD ["uvicorn", "backend.main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||
+7
-4
@@ -7,7 +7,7 @@ from fastapi.middleware.cors import CORSMiddleware
|
||||
from backend.config import settings
|
||||
from backend.api import upload, split, status, download
|
||||
from backend.api.websocket import router as websocket_router
|
||||
from backend.services import progress_publisher # Import the module
|
||||
from backend.services import progress_publisher
|
||||
|
||||
app = FastAPI(
|
||||
title="Audio Splitter Web API",
|
||||
@@ -24,9 +24,12 @@ app.add_middleware(
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Store the main event loop in the progress_publisher module
|
||||
# This avoids a circular import
|
||||
progress_publisher.MAIN_LOOP = asyncio.get_running_loop()
|
||||
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
"""Store the main event loop for use in other threads."""
|
||||
progress_publisher.MAIN_LOOP = asyncio.get_running_loop()
|
||||
|
||||
|
||||
# Include routers
|
||||
app.include_router(upload.router)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fastapi>=0.104.0
|
||||
uvicorn[standard]>=0.24.0
|
||||
python-multipart>=0.0.6
|
||||
aiofiles>=23.2.0
|
||||
pydantic>=2.5.0
|
||||
pydantic-settings>=2.0.0
|
||||
python-dotenv>=1.0.0
|
||||
websockets>=12.0
|
||||
@@ -5,7 +5,7 @@ from typing import Dict, Set
|
||||
|
||||
from fastapi import WebSocket
|
||||
|
||||
# This will be set by main.py when the app starts
|
||||
# This will be set by main.py during startup
|
||||
MAIN_LOOP = None
|
||||
|
||||
active_connections: Dict[str, Set[WebSocket]] = {}
|
||||
@@ -29,13 +29,19 @@ def publish_progress(task_id: str, progress: int, message: str, status: str = "p
|
||||
}
|
||||
|
||||
to_remove = set()
|
||||
# Get the loop to use: either the stored one or try to get the current loop
|
||||
loop = MAIN_LOOP
|
||||
if loop is None:
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
except RuntimeError:
|
||||
# No running loop, fallback to default event loop
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
for websocket in active_connections.get(task_id, set()):
|
||||
try:
|
||||
# Use the stored main loop, or fallback to getting the current loop
|
||||
loop = MAIN_LOOP or asyncio.get_running_loop()
|
||||
asyncio.run_coroutine_threadsafe(websocket.send_json(data), loop)
|
||||
except Exception:
|
||||
# Client disconnected or other error
|
||||
to_remove.add(websocket)
|
||||
|
||||
# Clean up disconnected clients
|
||||
|
||||
Reference in New Issue
Block a user