169 lines
5.2 KiB
PowerShell
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
|
|
}
|
|
}
|