SIP_GoldBees_Backend/start_all.ps1
2026-02-01 13:57:30 +00:00

169 lines
5.2 KiB
PowerShell

$ErrorActionPreference = "Stop"
$root = Split-Path -Parent $MyInvocation.MyCommand.Path
$stateDir = Join-Path $root ".orchestration"
$pidFile = Join-Path $stateDir "pids.json"
$python = Join-Path $root ".venv\\Scripts\\python.exe"
$status = [ordered]@{}
$engineExternal = $env:ENGINE_EXTERNAL -and $env:ENGINE_EXTERNAL.ToLower() -in @("1", "true", "yes")
if (-not $env:DB_HOST) { $env:DB_HOST = "localhost" }
if (-not $env:DB_PORT) { $env:DB_PORT = "5432" }
if (-not $env:DB_NAME) { $env:DB_NAME = "trading_db" }
if (-not $env:DB_USER) { $env:DB_USER = "trader" }
if (-not $env:DB_PASSWORD) { $env:DB_PASSWORD = "traderpass" }
if (-not $env:PGHOST) { $env:PGHOST = $env:DB_HOST }
if (-not $env:PGPORT) { $env:PGPORT = $env:DB_PORT }
if (-not $env:PGDATABASE) { $env:PGDATABASE = $env:DB_NAME }
if (-not $env:PGUSER) { $env:PGUSER = $env:DB_USER }
if (-not $env:PGPASSWORD) { $env:PGPASSWORD = $env:DB_PASSWORD }
function Write-Status {
param(
[string]$Label,
[bool]$Ok,
[string]$Detail = ""
)
if ($Ok) {
$status[$Label] = "OK"
Write-Host ("[OK] {0} {1}" -f $Label, $Detail) -ForegroundColor Green
} else {
$status[$Label] = "FAIL"
Write-Host ("[FAIL] {0} {1}" -f $Label, $Detail) -ForegroundColor Red
}
}
if (-not (Test-Path $python)) {
Write-Status "Python venv" $false $python
exit 1
}
Write-Status "Python venv" $true $python
New-Item -ItemType Directory -Force -Path $stateDir | Out-Null
if (Test-Path $pidFile) {
try {
$pids = Get-Content $pidFile | ConvertFrom-Json
$running = $false
foreach ($name in @("backend", "engine", "frontend")) {
$pid = $pids.$name
if ($pid) {
$proc = Get-Process -Id $pid -ErrorAction SilentlyContinue
if ($proc) { $running = $true }
}
}
if ($running) {
Write-Host "Services already running. Use .\\stop_all.ps1 to stop."
exit 0
}
} catch {
Remove-Item $pidFile -Force -ErrorAction SilentlyContinue
}
}
Write-Host "Starting PostgreSQL (docker)..."
$pgRunning = ""
docker ps --filter "name=trading_postgres" --format "{{.ID}}" | ForEach-Object { $pgRunning = $_ }
if ($LASTEXITCODE -ne 0) {
Write-Status "Docker" $false "not running"
exit 1
}
Write-Status "Docker" $true "running"
if (-not $pgRunning) {
docker compose up -d postgres
if ($LASTEXITCODE -ne 0) {
Write-Status "PostgreSQL" $false "failed to start"
exit 1
}
}
Write-Status "PostgreSQL" $true "container up"
Write-Host "Applying migrations..."
if (Test-Path (Join-Path $root "alembic.ini")) {
& $python -m alembic upgrade head
} elseif (Test-Path (Join-Path $root "backend\\alembic.ini")) {
& $python -m alembic -c (Join-Path $root "backend\\alembic.ini") upgrade head
}
& $python (Join-Path $root "backend\\scripts\\run_migrations.py")
if ($LASTEXITCODE -ne 0) {
Write-Status "Migrations" $false "failed"
exit 1
}
Write-Status "Migrations" $true "applied"
Write-Host "Starting backend..."
$backendCmd = "& { `$env:PYTHONPATH = '$root;$root\\backend'; cd '$root\\backend'; & '$python' -m uvicorn app.main:app --reload }"
$backendProc = Start-Process -FilePath "powershell" -ArgumentList @(
"-NoExit",
"-Command",
$backendCmd
) -PassThru
Write-Status "Backend" $true "pid $($backendProc.Id)"
if ($engineExternal) {
Write-Host "Starting engine runner..."
$engineCmd = "& { `$env:PYTHONPATH = '$root;$root\\backend'; cd '$root'; & '$python' -m indian_paper_trading_strategy.engine.engine_runner }"
$engineProc = Start-Process -FilePath "powershell" -ArgumentList @(
"-NoExit",
"-Command",
$engineCmd
) -PassThru
Write-Status "Engine" $true "pid $($engineProc.Id)"
} else {
Write-Host "Engine runner skipped (ENGINE_EXTERNAL not set). Backend will run engine."
Write-Status "Engine" $true "embedded"
}
Write-Host "Starting frontend..."
$frontendProc = Start-Process -FilePath "powershell" -ArgumentList @(
"-NoExit",
"-Command",
"cd '$root\\frontend'; npm run dev"
) -PassThru
Write-Status "Frontend" $true "pid $($frontendProc.Id)"
@{
backend = $backendProc.Id
engine = if ($engineExternal) { $engineProc.Id } else { $null }
frontend = $frontendProc.Id
started_at = (Get-Date).ToString("o")
} | ConvertTo-Json | Set-Content -Encoding ascii $pidFile
Write-Host "Waiting for backend health..."
$healthUrl = "http://localhost:8000/health"
$deadline = [DateTime]::UtcNow.AddMinutes(2)
$healthy = $false
while ([DateTime]::UtcNow -lt $deadline) {
try {
$resp = Invoke-WebRequest -Uri $healthUrl -UseBasicParsing -TimeoutSec 2
if ($resp.StatusCode -eq 200) {
$healthy = $true
break
}
} catch {
Start-Sleep -Seconds 2
}
}
if ($healthy) {
Write-Status "Backend health" $true $healthUrl
Write-Host ""
Write-Host "System online at http://localhost:3000/admin"
Start-Process "http://localhost:3000/admin"
} else {
Write-Status "Backend health" $false $healthUrl
Write-Host "Backend health check failed. Open http://localhost:3000/admin manually."
}
Write-Host ""
Write-Host "Summary:"
foreach ($entry in $status.GetEnumerator()) {
$label = $entry.Key
$value = $entry.Value
if ($value -eq "OK") {
Write-Host (" [OK] {0}" -f $label) -ForegroundColor Green
} else {
Write-Host (" [FAIL] {0}" -f $label) -ForegroundColor Red
}
}