#!/usr/bin/env bash set -eu # Real Estate Crawler - Development Server # Usage: # ./start.sh - Start with Docker (recommended) # ./start.sh --local - Start locally (requires Poetry and dependencies) # ./start.sh --help - Show help show_help() { echo "Real Estate Crawler - Development Server" echo "" echo "Usage: ./start.sh [OPTIONS]" echo "" echo "Options:" echo " (default) Start all services with Docker Compose" echo " --local Run locally with Poetry (requires local deps)" echo " --build Rebuild Docker images before starting" echo " --down Stop and remove all containers" echo " --logs Follow logs from all services" echo " --help Show this help message" echo "" echo "Examples:" echo " ./start.sh # Start with Docker" echo " ./start.sh --build # Rebuild and start" echo " ./start.sh --local # Run locally with Poetry" } start_docker() { local build_flag="" if [[ "${1:-}" == "--build" ]]; then build_flag="--build" fi echo "🐳 Starting services with Docker Compose..." echo "" # Check if docker/podman is available if command -v docker &> /dev/null; then COMPOSE_CMD="docker compose" elif command -v podman-compose &> /dev/null; then COMPOSE_CMD="podman-compose" else echo "❌ Error: Neither docker nor podman-compose found." echo " Install Docker: https://docs.docker.com/get-docker/" echo " Or run locally: ./start.sh --local" exit 1 fi $COMPOSE_CMD up $build_flag } stop_docker() { echo "🛑 Stopping all containers..." if command -v docker &> /dev/null; then docker compose down elif command -v podman-compose &> /dev/null; then podman-compose down fi } show_logs() { if command -v docker &> /dev/null; then docker compose logs -f elif command -v podman-compose &> /dev/null; then podman-compose logs -f fi } start_local() { echo "🛠️ Starting locally with Poetry..." echo "" # Check Poetry is available if ! command -v poetry &> /dev/null; then echo "❌ Error: Poetry not found." echo " Install: curl -sSL https://install.python-poetry.org | python3 -" echo " Or use Docker: ./start.sh" exit 1 fi # Source .env if it exists if [[ -f .env ]]; then set -a source .env set +a fi ENV_MODE=${ENV:-"dev"} # Ensure Redis is running if ! nc -z localhost 6379 2>/dev/null; then echo "📦 Starting Redis container..." docker run -d --rm --name rec-redis-local -p 6379:6379 redis:latest || true sleep 2 fi echo "✅ Redis OK" # Test celery connection poetry run python celery_app.py # Start Celery worker in background echo "🔧 Starting Celery worker..." if [[ "$ENV_MODE" == "dev" ]]; then poetry run celery -A celery_app worker --loglevel=info & else poetry run alembic upgrade head poetry run celery -A celery_app worker --beat --loglevel=info & fi CELERY_PID=$! cleanup() { echo "" echo "🛑 Stopping Celery worker (PID: $CELERY_PID)..." kill "$CELERY_PID" 2>/dev/null || true wait "$CELERY_PID" 2>/dev/null || true } trap cleanup EXIT SIGINT SIGTERM # Start uvicorn echo "🚀 Starting API server on http://localhost:5001" echo "" poetry run uvicorn api.app:app --host 0.0.0.0 --port 5001 --reload } # Parse arguments case "${1:-}" in --help|-h) show_help ;; --local) start_local ;; --down) stop_docker ;; --logs) show_logs ;; --build) start_docker --build ;; "") start_docker ;; *) echo "❌ Unknown option: $1" echo "" show_help exit 1 ;; esac