#!/bin/bash # scripts/start-api-and-workers.sh # Starts API and Workers using dotnet run (not Docker) # This script is called by start-task-docker.sh after database is ready # IMPORTANT: This script runs from the current working directory (Vibe Kanban worktree) TASK_ID=$1 PORT_OFFSET=${2:-0} # Use Vibe Kanban worktree if available, otherwise use current directory # This ensures we're running from the worktree, not the main repo if [ -n "$VIBE_WORKTREE_ROOT" ] && [ -d "$VIBE_WORKTREE_ROOT/src/Managing.Api" ]; then PROJECT_ROOT="$VIBE_WORKTREE_ROOT" echo "📁 Using Vibe Kanban worktree: $PROJECT_ROOT" else PROJECT_ROOT="$(pwd)" echo "📁 Using current directory: $PROJECT_ROOT" fi SCRIPT_DIR="$PROJECT_ROOT/scripts" POSTGRES_PORT=$((5432 + PORT_OFFSET)) API_PORT=$((5000 + PORT_OFFSET)) REDIS_PORT=$((6379 + PORT_OFFSET)) ORLEANS_SILO_PORT=$((11111 + PORT_OFFSET)) ORLEANS_GATEWAY_PORT=$((30000 + PORT_OFFSET)) # Convert to lowercase (compatible with bash 3.2+) DB_NAME="managing_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')" ORLEANS_DB_NAME="orleans_$(echo "$TASK_ID" | tr '[:upper:]' '[:lower:]')" # Extract TASK_SLOT from TASK_ID numeric part (e.g., TASK-5439 -> 5439) # This ensures unique Orleans ports for each task and prevents port conflicts # Use TASK_SLOT from environment if already set (from vibe-setup.sh config), otherwise extract from TASK_ID if [ -z "$TASK_SLOT" ] || [ "$TASK_SLOT" = "0" ]; then TASK_SLOT=$(echo "$TASK_ID" | grep -oE '[0-9]+' | head -1) if [ -z "$TASK_SLOT" ] || [ "$TASK_SLOT" = "0" ]; then # Fallback: use port offset calculation if TASK_ID doesn't contain numbers TASK_SLOT=$((PORT_OFFSET / 10 + 1)) echo "⚠️ TASK_ID doesn't contain a number, using port offset-based TASK_SLOT: $TASK_SLOT" else echo "📊 TASK_SLOT extracted from TASK_ID: $TASK_SLOT" fi else echo "📊 Using TASK_SLOT from configuration: $TASK_SLOT" fi # TASK_SLOT determines Orleans ports: Silo = 11111 + (TASK_SLOT - 1) * 10, Gateway = 30000 + (TASK_SLOT - 1) * 10 # PID files for process management PID_DIR="$PROJECT_ROOT/.task-pids" mkdir -p "$PID_DIR" API_PID_FILE="$PID_DIR/api-${TASK_ID}.pid" WORKERS_PID_FILE="$PID_DIR/workers-${TASK_ID}.pid" # Set environment variables for API export ASPNETCORE_ENVIRONMENT=Development export ASPNETCORE_URLS="http://localhost:${API_PORT}" export RUN_ORLEANS_GRAINS=true export SILO_ROLE=Trading export TASK_SLOT=${TASK_SLOT} export TASK_ID=${TASK_ID} export PORT_OFFSET=${PORT_OFFSET} # Orleans ports are calculated from TASK_SLOT in the application # These exports are kept for reference but not used (TASK_SLOT is the source of truth) export PostgreSql__ConnectionString="Host=localhost;Port=${POSTGRES_PORT};Database=${DB_NAME};Username=postgres;Password=postgres" export PostgreSql__Orleans="Host=localhost;Port=${POSTGRES_PORT};Database=${ORLEANS_DB_NAME};Username=postgres;Password=postgres" export InfluxDb__Url="http://localhost:8086/" export InfluxDb__Token="Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA==" export Jwt__Secret="2ed5f490-b6c1-4cad-8824-840c911f1fe6" export Privy__AppSecret="63Chz2z5M8TgR5qc8dznSLRAGTHTyPU4cjdQobrBF1Cx5tszZpTuFgyrRd7hZ2k6HpwDz3GEwQZzsCqHb8Z311bF" export AdminUsers="did:privy:cm7vxs99f0007blcl8cmzv74t;did:privy:cmhp5jqs2014kl60cbunp57jh" export AUTHORIZED_ADDRESSES="0x932167388dD9aad41149b3cA23eBD489E2E2DD78;0x84e3E147c4e94716151181F25538aBf337Eca49f;0xeaf2a9a5864e3Cc37E85dDC287Ed0c90d76b2420" export ENABLE_COPY_TRADING_VALIDATION=false export KAIGEN_CREDITS_ENABLED=false export KAIGEN_SECRET_KEY="KaigenXCowchain" export Flagsmith__ApiKey="ser.ShJJJMtWYS9fwuzd83ejwR" export Discord__ApplicationId="966075382002516031" export Discord__PublicKey="63028f6bb740cd5d26ae0340b582dee2075624011b28757436255fc002ca8a7c" export Discord__TokenId="OTY2MDc1MzgyMDAyNTE2MDMx.Yl8dzw.xpeIAaMwGrwTNY4r9JYv0ebzb-U" export N8n__WebhookUrl="https://n8n.kai.managing.live/webhook/fa9308b6-983b-42ec-b085-71599d655951" export N8n__IndicatorRequestWebhookUrl="https://n8n.kai.managing.live/webhook/3aa07b66-1e64-46a7-8618-af300914cb11" export N8n__Username="managing-api" export N8n__Password="T259836*PdiV2@%!eR%Qf4" export Sentry__Dsn="https://fe12add48c56419bbdfa86227c188e7a@glitch.kai.managing.live/1" # Verify we're in the right directory (should have src/Managing.Api) if [ ! -d "$PROJECT_ROOT/src/Managing.Api" ]; then echo "❌ Error: src/Managing.Api not found in current directory: $PROJECT_ROOT" echo "💡 Make sure you're running from the project root (or Vibe Kanban worktree)" exit 1 fi echo "🚀 Starting API on port $API_PORT..." echo "📁 Running from: $PROJECT_ROOT" cd "$PROJECT_ROOT/src/Managing.Api" # Write all output to log file (warnings will be filtered when displaying) dotnet run > "$PID_DIR/api-${TASK_ID}.log" 2>&1 & API_PID=$! echo $API_PID > "$API_PID_FILE" echo "✅ API started (PID: $API_PID) from worktree: $PROJECT_ROOT" # Wait a bit for API to start sleep 3 echo "🚀 Starting Workers..." cd "$PROJECT_ROOT/src/Managing.Workers" # Set workers environment variables (separate from API) # Write all output to log file (warnings will be filtered when displaying) ASPNETCORE_ENVIRONMENT=Development \ PostgreSql__ConnectionString="Host=localhost;Port=${POSTGRES_PORT};Database=${DB_NAME};Username=postgres;Password=postgres" \ InfluxDb__Url="http://localhost:8086/" \ InfluxDb__Token="Fw2FPL2OwTzDHzSbR2Sd5xs0EKQYy00Q-hYKYAhr9cC1_q5YySONpxuf_Ck0PTjyUiF13xXmi__bu_pXH-H9zA==" \ KAIGEN_SECRET_KEY="KaigenXCowchain" \ Flagsmith__ApiKey="ser.ShJJJMtWYS9fwuzd83ejwR" \ dotnet run > "$PID_DIR/workers-${TASK_ID}.log" 2>&1 & WORKERS_PID=$! echo $WORKERS_PID > "$WORKERS_PID_FILE" echo "✅ Workers started (PID: $WORKERS_PID) from worktree: $PROJECT_ROOT" echo "" echo "✅ API and Workers started!" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" echo "📊 API: http://localhost:$API_PORT" echo "📋 API PID: $API_PID" echo "📋 Workers PID: $WORKERS_PID" echo "📋 Logs: $PID_DIR/api-${TASK_ID}.log" echo "📋 Logs: $PID_DIR/workers-${TASK_ID}.log" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"