Spaces:
Sleeping
Sleeping
| # ============================================================ | |
| # SchemeImpactNet β Start Script | |
| # Usage: ./start.sh [options] | |
| # | |
| # Options: | |
| # --skip-pipeline Skip data generation even if files missing | |
| # --backend-only Start only the FastAPI backend | |
| # --frontend-only Start only the Streamlit frontend | |
| # --port-backend N Backend port (default: 8000) | |
| # --port-frontend N Frontend port (default: 8501) | |
| # --stage N Pipeline stage to run if needed (1|2|3, default: 3) | |
| # ============================================================ | |
| set -euo pipefail | |
| # ββ Defaults ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| BACKEND_PORT=8000 | |
| FRONTEND_PORT=8501 | |
| PIPELINE_STAGE=3 | |
| SKIP_PIPELINE=false | |
| BACKEND_ONLY=false | |
| FRONTEND_ONLY=false | |
| BACKEND_PID="" | |
| FRONTEND_PID="" | |
| # ββ Always resolve project root (where this script lives) βββββββββββββββββββββ | |
| PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| # ββ Colours βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| AMBER='\033[0;33m' | |
| BLUE='\033[0;34m' | |
| BOLD='\033[1m' | |
| RESET='\033[0m' | |
| ok() { echo -e "${GREEN} β${RESET} $*"; } | |
| info() { echo -e "${BLUE} β${RESET} $*"; } | |
| warn() { echo -e "${AMBER} β ${RESET} $*"; } | |
| err() { echo -e "${RED} β${RESET} $*"; } | |
| hr() { echo -e "${BOLD}ββββββββββββββββββββββββββββββββββββββββββββββββββ${RESET}"; } | |
| # ββ Arg parsing βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| while [[ $# -gt 0 ]]; do | |
| case $1 in | |
| --skip-pipeline) SKIP_PIPELINE=true ;; | |
| --backend-only) BACKEND_ONLY=true ;; | |
| --frontend-only) FRONTEND_ONLY=true ;; | |
| --port-backend) | |
| BACKEND_PORT="$2" | |
| shift | |
| ;; | |
| --port-frontend) | |
| FRONTEND_PORT="$2" | |
| shift | |
| ;; | |
| --stage) | |
| PIPELINE_STAGE="$2" | |
| shift | |
| ;; | |
| *) warn "Unknown option: $1" ;; | |
| esac | |
| shift | |
| done | |
| # ββ Cleanup handler βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| cleanup() { | |
| echo "" | |
| hr | |
| info "Shutting down servicesβ¦" | |
| [[ -n "$BACKEND_PID" ]] && kill "$BACKEND_PID" 2>/dev/null && ok "Backend stopped" | |
| [[ -n "$FRONTEND_PID" ]] && kill "$FRONTEND_PID" 2>/dev/null && ok "Frontend stopped" | |
| hr | |
| } | |
| trap cleanup EXIT INT TERM | |
| # ββ Banner ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| echo "" | |
| echo -e "${BOLD} β SchemeImpactNet β Service Manager${RESET}" | |
| hr | |
| echo "" | |
| # ββ Prerequisite checks βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| info "Checking prerequisitesβ¦" | |
| if ! command -v python &>/dev/null && ! command -v python3 &>/dev/null; then | |
| err "Python not found. Install Python 3.9+." | |
| exit 1 | |
| fi | |
| PYTHON=$(command -v python3 2>/dev/null || command -v python) | |
| ok "Python β $($PYTHON --version 2>&1)" | |
| if ! $PYTHON -m uvicorn --version &>/dev/null; then | |
| warn "uvicorn not found β attempting installβ¦" | |
| $PYTHON -m pip install "uvicorn[standard]" --quiet || { | |
| err "uvicorn install failed." | |
| exit 1 | |
| } | |
| fi | |
| ok "uvicorn ready" | |
| if ! $PYTHON -m streamlit --version &>/dev/null; then | |
| warn "streamlit not found β attempting installβ¦" | |
| $PYTHON -m pip install streamlit --quiet || { | |
| err "streamlit install failed." | |
| exit 1 | |
| } | |
| fi | |
| STREAMLIT_VER=$($PYTHON -m streamlit --version 2>&1 | awk '{print $3}') | |
| ok "streamlit $STREAMLIT_VER ready" | |
| STREAMLIT_MAJOR=$(echo "$STREAMLIT_VER" | cut -d. -f1) | |
| STREAMLIT_MINOR=$(echo "$STREAMLIT_VER" | cut -d. -f2) | |
| if [[ "$STREAMLIT_MAJOR" -lt 1 ]] || { [[ "$STREAMLIT_MAJOR" -eq 1 ]] && [[ "$STREAMLIT_MINOR" -lt 36 ]]; }; then | |
| warn "Streamlit $STREAMLIT_VER β upgrade to 1.36+ for st.navigation():" | |
| warn " pip install --upgrade streamlit" | |
| fi | |
| if [[ ! -f "$PROJECT_ROOT/frontend/app.py" ]]; then | |
| err "frontend/app.py not found at $PROJECT_ROOT/frontend/app.py" | |
| exit 1 | |
| fi | |
| ok "frontend/app.py found" | |
| if [[ ! -f "$PROJECT_ROOT/backend/main.py" ]]; then | |
| err "backend/main.py not found at $PROJECT_ROOT/backend/main.py" | |
| exit 1 | |
| fi | |
| ok "backend/main.py found" | |
| echo "" | |
| # ββ Data pipeline βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if [[ "$FRONTEND_ONLY" == false && "$SKIP_PIPELINE" == false ]]; then | |
| PROCESSED_FILES=( | |
| "$PROJECT_ROOT/data/processed/mnrega_cleaned.csv" | |
| "$PROJECT_ROOT/data/processed/mnrega_predictions.csv" | |
| "$PROJECT_ROOT/data/processed/optimized_budget_allocation.csv" | |
| ) | |
| MISSING=false | |
| for f in "${PROCESSED_FILES[@]}"; do | |
| if [[ ! -f "$f" ]]; then | |
| warn "Missing: $f" | |
| MISSING=true | |
| fi | |
| done | |
| if [[ "$MISSING" == true ]]; then | |
| hr | |
| info "Processed data not found β running Stage $PIPELINE_STAGE pipelineβ¦" | |
| info "This may take several minutes on first run." | |
| hr | |
| echo "" | |
| cd "$PROJECT_ROOT" && $PYTHON main.py --stage "$PIPELINE_STAGE" || { | |
| err "Pipeline failed. Check errors above." | |
| exit 1 | |
| } | |
| echo "" | |
| ok "Pipeline complete" | |
| hr | |
| echo "" | |
| else | |
| ok "Processed data found β skipping pipeline" | |
| for f in "${PROCESSED_FILES[@]}"; do | |
| info " $(basename $f) ($(wc -l <"$f") rows)" | |
| done | |
| echo "" | |
| fi | |
| fi | |
| # ββ Start backend βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if [[ "$FRONTEND_ONLY" == false ]]; then | |
| if lsof -i ":$BACKEND_PORT" &>/dev/null 2>&1; then | |
| warn "Port $BACKEND_PORT already in use β stopping existing processβ¦" | |
| lsof -ti ":$BACKEND_PORT" | xargs kill -9 2>/dev/null || true | |
| sleep 1 | |
| fi | |
| info "Starting FastAPI backend on port $BACKEND_PORTβ¦" | |
| # Backend must run from project root so 'backend.main' import resolves | |
| (cd "$PROJECT_ROOT" && $PYTHON -m uvicorn backend.main:app \ | |
| --host 0.0.0.0 \ | |
| --port "$BACKEND_PORT" \ | |
| --reload \ | |
| --log-level warning \ | |
| 2>&1 | sed "s/^/ [backend] /") & | |
| BACKEND_PID=$! | |
| info "Waiting for backend health checkβ¦" | |
| MAX_WAIT=15 | |
| WAITED=0 | |
| until curl -sf "http://localhost:$BACKEND_PORT/health" &>/dev/null; do | |
| sleep 1 | |
| WAITED=$((WAITED + 1)) | |
| if [[ $WAITED -ge $MAX_WAIT ]]; then | |
| warn "Backend health check timed out after ${MAX_WAIT}s β continuing anyway" | |
| break | |
| fi | |
| done | |
| curl -sf "http://localhost:$BACKEND_PORT/health" &>/dev/null && ok "Backend live β http://localhost:$BACKEND_PORT" | |
| echo "" | |
| fi | |
| # ββ Start frontend ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if [[ "$BACKEND_ONLY" == false ]]; then | |
| if lsof -i ":$FRONTEND_PORT" &>/dev/null 2>&1; then | |
| warn "Port $FRONTEND_PORT already in use β stopping existing processβ¦" | |
| lsof -ti ":$FRONTEND_PORT" | xargs kill -9 2>/dev/null || true | |
| sleep 1 | |
| fi | |
| info "Starting Streamlit frontend on port $FRONTEND_PORTβ¦" | |
| cd "$PROJECT_ROOT/frontend" | |
| $PYTHON -m streamlit run app.py --server.port "$FRONTEND_PORT" --server.headless true --browser.gatherUsageStats false & | |
| FRONTEND_PID=$! | |
| cd "$PROJECT_ROOT" | |
| sleep 2 | |
| ok "Frontend live β http://localhost:$FRONTEND_PORT" | |
| echo "" | |
| fi | |
| # ββ Ready banner ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| hr | |
| echo "" | |
| echo -e "${BOLD} β SchemeImpactNet is running${RESET}" | |
| echo "" | |
| [[ "$FRONTEND_ONLY" == false ]] && echo -e " ${GREEN}Backend${RESET} http://localhost:$BACKEND_PORT" | |
| [[ "$FRONTEND_ONLY" == false ]] && echo -e " ${GREEN}API docs${RESET} http://localhost:$BACKEND_PORT/docs" | |
| [[ "$BACKEND_ONLY" == false ]] && echo -e " ${GREEN}Dashboard${RESET} http://localhost:$FRONTEND_PORT" | |
| echo "" | |
| echo -e " ${BOLD}Press Ctrl+C to stop all services${RESET}" | |
| echo "" | |
| hr | |
| echo "" | |
| # ββ Keep alive ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| wait | |