#!/usr/bin/env bash # Restart local development app services for Seg_Server. # Infra services (PostgreSQL/Redis/MinIO) are checked and started if possible. set -euo pipefail PROJECT_DIR="${PROJECT_DIR:-/home/wkmgc/Desktop/Seg_Server}" CONDA_ENV="${CONDA_ENV:-seg_server}" CONDA_BIN="${CONDA_BIN:-${HOME}/miniconda3/bin/conda}" BACKEND_PORT="${BACKEND_PORT:-8000}" FRONTEND_PORT="${FRONTEND_PORT:-3000}" LOG_DIR="${LOG_DIR:-/tmp}" PID_DIR="${PID_DIR:-/tmp}" FASTAPI_LOG="${LOG_DIR}/seg_server_fastapi.log" CELERY_LOG="${LOG_DIR}/seg_server_celery.log" FRONTEND_LOG="${LOG_DIR}/seg_server_frontend.log" MINIO_LOG="${LOG_DIR}/seg_server_minio.log" FASTAPI_PID="${PID_DIR}/seg_server_fastapi.pid" CELERY_PID="${PID_DIR}/seg_server_celery.pid" FRONTEND_PID="${PID_DIR}/seg_server_frontend.pid" MINIO_PID="${PID_DIR}/seg_server_minio.pid" echo "== Seg_Server development restart ==" echo "Project: ${PROJECT_DIR}" start_system_service() { local service_name="$1" if command -v systemctl >/dev/null 2>&1; then sudo systemctl start "${service_name}" else echo "systemctl not found; please start ${service_name} manually." >&2 return 1 fi } ensure_conda() { if [[ -x "${CONDA_BIN}" ]]; then return fi if command -v conda >/dev/null 2>&1; then CONDA_BIN="$(command -v conda)" return fi echo "conda not found; set CONDA_BIN to the conda executable." >&2 exit 1 } stop_pidfile_group() { local pidfile="$1" if [[ ! -f "${pidfile}" ]]; then return fi local pid pid="$(cat "${pidfile}" 2>/dev/null || true)" rm -f "${pidfile}" if [[ -z "${pid}" ]]; then return fi if kill -0 "${pid}" >/dev/null 2>&1; then kill -- "-${pid}" >/dev/null 2>&1 || kill "${pid}" >/dev/null 2>&1 || true fi } start_detached() { local name="$1" local workdir="$2" local pidfile="$3" local logfile="$4" shift 4 mkdir -p "$(dirname "${pidfile}")" "$(dirname "${logfile}")" : >"${logfile}" setsid bash -c 'cd "$1" || exit 1; shift; exec "$@"' bash "${workdir}" "$@" >"${logfile}" 2>&1 < /dev/null & local pid=$! echo "${pid}" >"${pidfile}" echo " ${name} pid ${pid}" } wait_for_http() { local label="$1" local url="$2" local logfile="$3" local method="${4:-GET}" for _ in $(seq 1 30); do if [[ "${method}" == "HEAD" ]]; then curl -fsS -I "${url}" >/dev/null 2>&1 && echo " ${label} ready" && return else curl -fsS "${url}" >/dev/null 2>&1 && echo " ${label} ready" && return fi sleep 1 done echo "${label} did not become ready: ${url}" >&2 echo "Last log lines from ${logfile}:" >&2 tail -n 80 "${logfile}" >&2 || true exit 1 } ensure_conda echo "[1/6] Checking PostgreSQL..." if ! pg_isready -q; then start_system_service postgresql fi pg_isready >/dev/null echo " PostgreSQL ready" echo "[2/6] Checking Redis..." if ! redis-cli ping >/dev/null 2>&1; then start_system_service redis-server fi redis-cli ping >/dev/null echo " Redis ready" echo "[3/6] Checking MinIO..." if ! curl -fsS http://localhost:9000/minio/health/live >/dev/null 2>&1; then stop_pidfile_group "${MINIO_PID}" start_detached "MinIO" "${PROJECT_DIR}" "${MINIO_PID}" "${MINIO_LOG}" minio server "${HOME}/minio_data" --console-address :9001 fi wait_for_http "MinIO" "http://localhost:9000/minio/health/live" "${MINIO_LOG}" echo "[4/6] Stopping app services..." stop_pidfile_group "${FASTAPI_PID}" stop_pidfile_group "${CELERY_PID}" stop_pidfile_group "${FRONTEND_PID}" pkill -f "uvicorn main:app --host .*--port ${BACKEND_PORT}" || true pkill -f "uvicorn main:app" || true pkill -f "conda run -n ${CONDA_ENV} uvicorn main:app" || true pkill -f "celery -A celery_app:celery_app worker" || true pkill -f "conda run -n ${CONDA_ENV} celery -A celery_app:celery_app worker" || true pkill -f "${PROJECT_DIR}/node_modules/.bin/tsx server.ts" || true pkill -f "npm run dev" || true sleep 1 echo "[5/6] Starting backend and worker..." start_detached "FastAPI" "${PROJECT_DIR}/backend" "${FASTAPI_PID}" "${FASTAPI_LOG}" \ "${CONDA_BIN}" run -n "${CONDA_ENV}" uvicorn main:app --host 0.0.0.0 --port "${BACKEND_PORT}" start_detached "Celery" "${PROJECT_DIR}/backend" "${CELERY_PID}" "${CELERY_LOG}" \ "${CONDA_BIN}" run -n "${CONDA_ENV}" celery -A celery_app:celery_app worker --loglevel=info --concurrency=1 echo "[6/6] Starting frontend..." start_detached "Frontend" "${PROJECT_DIR}" "${FRONTEND_PID}" "${FRONTEND_LOG}" npm run dev wait_for_http "FastAPI" "http://127.0.0.1:${BACKEND_PORT}/health" "${FASTAPI_LOG}" wait_for_http "Frontend" "http://127.0.0.1:${FRONTEND_PORT}" "${FRONTEND_LOG}" HEAD echo "== Restart complete ==" echo "Frontend: http://localhost:${FRONTEND_PORT}" echo "Backend: http://localhost:${BACKEND_PORT}/docs" echo "PID files:" echo " FastAPI: ${FASTAPI_PID}" echo " Celery: ${CELERY_PID}" echo " Frontend: ${FRONTEND_PID}" echo "Logs:" echo " FastAPI: ${FASTAPI_LOG}" echo " Celery: ${CELERY_LOG}" echo " Frontend: ${FRONTEND_LOG}" echo " MinIO: ${MINIO_LOG}"