digraph local_architecture { rankdir=TB node [shape=box, style=rounded, fontname="Helvetica"] edge [fontname="Helvetica", fontsize=10] labelloc="t" label="MPR - Local Architecture (Celery + MinIO)" fontsize=16 fontname="Helvetica-Bold" graph [splines=ortho, nodesep=0.8, ranksep=0.8] // External subgraph cluster_external { label="External" style=dashed color=gray browser [label="Browser\nmpr.local.ar", shape=ellipse] } // Nginx reverse proxy subgraph cluster_proxy { label="Reverse Proxy" style=filled fillcolor="#e8f4f8" nginx [label="nginx\nport 80"] } // Application layer subgraph cluster_apps { label="Application Layer" style=filled fillcolor="#f0f8e8" django [label="Django Admin\n/admin\nport 8701"] fastapi [label="FastAPI + GraphQL\n/api + /graphql\nport 8702"] timeline [label="Timeline UI\n/\nport 5173"] } // Worker layer subgraph cluster_workers { label="Worker Layer" style=filled fillcolor="#fff8e8" grpc_server [label="gRPC Server\nport 50051"] celery [label="Celery Worker\nFFmpeg transcoding"] } // Data layer subgraph cluster_data { label="Data Layer" style=filled fillcolor="#f8e8f0" postgres [label="PostgreSQL\nport 5436", shape=cylinder] redis [label="Redis\nCelery queue\nport 6381", shape=cylinder] } // Storage subgraph cluster_storage { label="S3 Storage (MinIO)" style=filled fillcolor="#f0f0f0" minio [label="MinIO\nS3-compatible API\nport 9000", shape=folder] bucket_in [label="mpr-media-in/\ninput videos", shape=note] bucket_out [label="mpr-media-out/\ntranscoded output", shape=note] } // Connections browser -> nginx [label="HTTP"] nginx -> django [xlabel="/admin"] nginx -> fastapi [xlabel="/api, /graphql"] nginx -> timeline [xlabel="/"] nginx -> minio [xlabel="/media/*"] timeline -> fastapi [label="REST API\nGraphQL"] django -> postgres fastapi -> postgres [label="read/write jobs"] fastapi -> grpc_server [label="gRPC\nprogress updates"] grpc_server -> celery [label="dispatch tasks"] celery -> redis [label="task queue"] celery -> postgres [label="update job status"] celery -> minio [label="S3 API\ndownload input\nupload output"] minio -> bucket_in [style=dotted, arrowhead=none] minio -> bucket_out [style=dotted, arrowhead=none] }