80 lines
3.2 KiB
Bash
80 lines
3.2 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||
|
|
SESSION_NAME="${SESSION_NAME:-social-dev}"
|
||
|
|
COMPOSE_FILE="$ROOT_DIR/infra/docker/docker-compose.yml"
|
||
|
|
ENV_FILE="$ROOT_DIR/.env"
|
||
|
|
|
||
|
|
echo "=== Dev App Up ==="
|
||
|
|
echo "This script assumes redis/supabase are already running via docker compose."
|
||
|
|
echo ""
|
||
|
|
|
||
|
|
if ! command -v tmux >/dev/null 2>&1; then
|
||
|
|
echo "Error: tmux is required." >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if ! command -v docker >/dev/null 2>&1; then
|
||
|
|
echo "Error: docker is required." >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ ! -f "$ENV_FILE" ]; then
|
||
|
|
echo "Error: env file not found at $ENV_FILE" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
if [ ! -f "$COMPOSE_FILE" ]; then
|
||
|
|
echo "Error: compose file not found at $COMPOSE_FILE" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
set -a
|
||
|
|
# shellcheck disable=SC1090
|
||
|
|
. "$ENV_FILE"
|
||
|
|
set +a
|
||
|
|
|
||
|
|
if tmux has-session -t "$SESSION_NAME" 2>/dev/null; then
|
||
|
|
echo "Error: tmux session '$SESSION_NAME' already exists." >&2
|
||
|
|
echo "Hint: tmux kill-session -t $SESSION_NAME" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "[1/2] Running bootstrap once (migrate + init-data)..."
|
||
|
|
running_services="$(docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" ps --status running --services || true)"
|
||
|
|
if ! printf '%s\n' "$running_services" | grep -qx "db"; then
|
||
|
|
echo "Error: db service is not running. Start infra first." >&2
|
||
|
|
echo "Hint: docker compose --env-file .env -f infra/docker/docker-compose.yml up -d" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
if ! printf '%s\n' "$running_services" | grep -qx "redis"; then
|
||
|
|
echo "Error: redis service is not running. Start infra first." >&2
|
||
|
|
echo "Hint: docker compose --env-file .env -f infra/docker/docker-compose.yml up -d" >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" --profile job run --rm init-job
|
||
|
|
|
||
|
|
echo "[2/2] Starting web + worker processes in tmux session '$SESSION_NAME'..."
|
||
|
|
|
||
|
|
WEB_CMD="cd '$ROOT_DIR' && PYTHONPATH=backend/src uv run gunicorn app:app --bind \
|
||
|
|
${SOCIAL_WEB__HOST:-0.0.0.0}:${SOCIAL_WEB__PORT:-8000} --workers \
|
||
|
|
${SOCIAL_WEB__GUNICORN__WORKERS:-2} --worker-class \
|
||
|
|
${SOCIAL_WEB__GUNICORN__WORKER_CLASS:-uvicorn.workers.UvicornWorker} --timeout \
|
||
|
|
${SOCIAL_WEB__GUNICORN__TIMEOUT:-60}"
|
||
|
|
|
||
|
|
WORKER_CRITICAL_CMD="cd '$ROOT_DIR' && PYTHONPATH=backend/src uv run celery -A core.celery.app worker --loglevel=info --queues=critical --concurrency=${SOCIAL_WORKER__GROUPS__CRITICAL__CONCURRENCY:-2}"
|
||
|
|
WORKER_DEFAULT_CMD="cd '$ROOT_DIR' && PYTHONPATH=backend/src uv run celery -A core.celery.app worker --loglevel=info --queues=default --concurrency=${SOCIAL_WORKER__GROUPS__DEFAULT__CONCURRENCY:-2}"
|
||
|
|
WORKER_BULK_CMD="cd '$ROOT_DIR' && PYTHONPATH=backend/src uv run celery -A core.celery.app worker --loglevel=info --queues=bulk --concurrency=${SOCIAL_WORKER__GROUPS__BULK__CONCURRENCY:-1}"
|
||
|
|
|
||
|
|
tmux new-session -d -s "$SESSION_NAME" -n web "bash -lc \"$WEB_CMD; echo '[web] exited'; exec bash\""
|
||
|
|
tmux new-window -t "$SESSION_NAME" -n worker-critical "bash -lc \"$WORKER_CRITICAL_CMD; echo '[worker-critical] exited'; exec bash\""
|
||
|
|
tmux new-window -t "$SESSION_NAME" -n worker-default "bash -lc \"$WORKER_DEFAULT_CMD; echo '[worker-default] exited'; exec bash\""
|
||
|
|
tmux new-window -t "$SESSION_NAME" -n worker-bulk "bash -lc \"$WORKER_BULK_CMD; echo '[worker-bulk] exited'; exec bash\""
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "=== Dev App Started ==="
|
||
|
|
echo "tmux attach -t $SESSION_NAME"
|
||
|
|
echo "tmux list-windows -t $SESSION_NAME"
|