fix(infra): resolve NestJS dist build and Prometheus target issues
NestJS: disable incremental in 6 services tsconfig.json to fix dist not emitted when nest-cli deleteOutDir conflicts with tsc tsbuildinfo. classes/iam: import HealthModule in AppModule to fix /healthz 404. classes: rewrite HealthController to Drizzle getDb from TypeORM DI. teacher-bff: add /metrics endpoint for Prometheus scraping. infra: add node/mysql/redis exporters to observability profile. mysql-exporter v0.15.1 uses command-line flags not DATA_SOURCE_NAME. prometheus: enable web.enable-lifecycle for hot reload.
This commit is contained in:
@@ -13,7 +13,8 @@
|
||||
.\scripts\start-all.ps1 -SkipInfraCheck
|
||||
#>
|
||||
param(
|
||||
[switch]$SkipInfraCheck
|
||||
[switch]$SkipInfraCheck,
|
||||
[switch]$Force
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
@@ -26,7 +27,7 @@ Write-Host ""
|
||||
|
||||
# ===== 1. Infrastructure health check =====
|
||||
if (-not $SkipInfraCheck) {
|
||||
Write-Host "[1/4] Checking infrastructure health..." -ForegroundColor Yellow
|
||||
Write-Host "[1/6] Checking infrastructure health..." -ForegroundColor Yellow
|
||||
$infraServices = @(
|
||||
@{Name="MySQL"; Container="edu-mysql"},
|
||||
@{Name="Redis"; Container="edu-redis"},
|
||||
@@ -64,7 +65,7 @@ if (-not $SkipInfraCheck) {
|
||||
}
|
||||
|
||||
# ===== 2. Environment variables =====
|
||||
Write-Host "[2/4] Preparing environment variables..." -ForegroundColor Yellow
|
||||
Write-Host "[2/6] Preparing environment variables..." -ForegroundColor Yellow
|
||||
|
||||
$env:DEV_MODE = "true"
|
||||
$env:OTEL_EXPORTER_OTLP_ENDPOINT = "http://localhost:4318"
|
||||
@@ -88,8 +89,103 @@ Write-Host " DEV_MODE=true (dev-token bypass)" -ForegroundColor Green
|
||||
Write-Host " OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# ===== 3. Start application services =====
|
||||
Write-Host "[3/4] Starting application services (11 windows)..." -ForegroundColor Yellow
|
||||
# ===== 3. Port conflict check =====
|
||||
Write-Host "[3/6] Checking port conflicts..." -ForegroundColor Yellow
|
||||
|
||||
$portMap = @{
|
||||
3001="classes"; 3002="iam"; 3003="teacher-bff"; 3004="core-edu"
|
||||
3005="content"; 3006="data-ana"; 3007="msg"; 3008="ai"
|
||||
8080="api-gateway"; 8081="push-gateway"; 3000="teacher-portal"
|
||||
}
|
||||
|
||||
$conflicts = @()
|
||||
foreach ($port in $portMap.Keys | Sort-Object) {
|
||||
$conn = Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction SilentlyContinue
|
||||
if ($conn) {
|
||||
$svcName = $portMap[$port]
|
||||
$procId = $conn[0].OwningProcess
|
||||
$procName = ""
|
||||
try { $procName = (Get-Process -Id $procId -ErrorAction Stop).ProcessName } catch {}
|
||||
Write-Host " [WARN] Port $port ($svcName) occupied by PID $procId ($procName)" -ForegroundColor Yellow
|
||||
$conflicts += [PSCustomObject]@{Port=$port; Service=$svcName; PID=$procId; Process=$procName}
|
||||
}
|
||||
}
|
||||
|
||||
if ($conflicts.Count -gt 0) {
|
||||
Write-Host ""
|
||||
Write-Host " $($conflicts.Count) port(s) already in use." -ForegroundColor Yellow
|
||||
|
||||
$shouldKill = $false
|
||||
if ($Force) {
|
||||
Write-Host " -Force specified, killing automatically..." -ForegroundColor White
|
||||
$shouldKill = $true
|
||||
} else {
|
||||
Write-Host " These services may already be running. Options:" -ForegroundColor White
|
||||
Write-Host " 1. Run .\scripts\stop-all.ps1 -KillByPort first, then re-run start-all" -ForegroundColor White
|
||||
Write-Host " 2. Re-run with -Force to auto-kill and continue" -ForegroundColor White
|
||||
Write-Host ""
|
||||
$answer = Read-Host " Kill existing processes and continue? (y/N)"
|
||||
if ($answer -eq "y" -or $answer -eq "Y") {
|
||||
$shouldKill = $true
|
||||
}
|
||||
}
|
||||
|
||||
if ($shouldKill) {
|
||||
foreach ($c in $conflicts) {
|
||||
try {
|
||||
Stop-Process -Id $c.PID -Force -ErrorAction Stop
|
||||
Write-Host " [OK] Killed PID $($c.PID) ($($c.Process)) on port $($c.Port)" -ForegroundColor Green
|
||||
Start-Sleep -Milliseconds 500
|
||||
} catch {
|
||||
Write-Host " [WARN] Cannot kill PID $($c.PID): $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
Start-Sleep -Seconds 2
|
||||
} else {
|
||||
Write-Host " Aborting. Please stop existing services first." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Host " [OK] All app ports are free" -ForegroundColor Green
|
||||
}
|
||||
Write-Host ""
|
||||
|
||||
# ===== 4. Build NestJS services (required for nest start --watch) =====
|
||||
Write-Host "[4/6] Building NestJS services (first time required)..." -ForegroundColor Yellow
|
||||
|
||||
$nestjsServices = @(
|
||||
"@edu/classes-service",
|
||||
"@edu/iam-service",
|
||||
"@edu/teacher-bff",
|
||||
"@edu/core-edu-service",
|
||||
"@edu/content-service",
|
||||
"@edu/msg-service"
|
||||
)
|
||||
|
||||
# Clean tsbuildinfo cache (incremental mode leftover causes tsc to skip emit)
|
||||
$nestjsDirs = @("classes", "iam", "teacher-bff", "core-edu", "content", "msg")
|
||||
foreach ($dir in $nestjsDirs) {
|
||||
$svcPath = Join-Path $ProjectRoot "services\$dir"
|
||||
if (Test-Path $svcPath) {
|
||||
Get-ChildItem -Path $svcPath -Filter "*.tsbuildinfo" -Recurse -ErrorAction SilentlyContinue |
|
||||
Remove-Item -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($svc in $nestjsServices) {
|
||||
Write-Host " Building $svc..." -ForegroundColor Gray -NoNewline
|
||||
$buildResult = pnpm --filter $svc build 2>&1
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host " [OK]" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host " [FAIL]" -ForegroundColor Red
|
||||
Write-Host " $buildResult" -ForegroundColor DarkGray
|
||||
}
|
||||
}
|
||||
Write-Host ""
|
||||
|
||||
# ===== 5. Start application services =====
|
||||
Write-Host "[5/6] Starting application services (11 windows)..." -ForegroundColor Yellow
|
||||
|
||||
$services = @(
|
||||
@{Title="edu-app-classes"; Cmd="pnpm"; Args=@("--filter","@edu/classes-service","dev"); Dir="$ProjectRoot"},
|
||||
@@ -98,8 +194,8 @@ $services = @(
|
||||
@{Title="edu-app-core-edu"; Cmd="pnpm"; Args=@("--filter","@edu/core-edu-service","dev"); Dir="$ProjectRoot"},
|
||||
@{Title="edu-app-content"; Cmd="pnpm"; Args=@("--filter","@edu/content-service","dev"); Dir="$ProjectRoot"},
|
||||
@{Title="edu-app-msg"; Cmd="pnpm"; Args=@("--filter","@edu/msg-service","dev"); Dir="$ProjectRoot"},
|
||||
@{Title="edu-app-data-ana"; Cmd="uv"; Args=@("run","uvicorn","data_ana.main:app","--host","0.0.0.0","--port","3006","--reload"); Dir="$ProjectRoot\services\data-ana"; PyEnv=$true},
|
||||
@{Title="edu-app-ai"; Cmd="uv"; Args=@("run","uvicorn","ai.main:app","--host","0.0.0.0","--port","3008","--reload"); Dir="$ProjectRoot\services\ai"; PyEnv=$true},
|
||||
@{Title="edu-app-data-ana"; Cmd="uv"; Args=@("run","uvicorn","data_ana.main:app","--app-dir","src","--host","0.0.0.0","--port","3006","--reload"); Dir="$ProjectRoot\services\data-ana"; PyEnv=$true},
|
||||
@{Title="edu-app-ai"; Cmd="uv"; Args=@("run","uvicorn","ai.main:app","--app-dir","src","--host","0.0.0.0","--port","3008","--reload"); Dir="$ProjectRoot\services\ai"; PyEnv=$true},
|
||||
@{Title="edu-app-api-gateway"; Cmd="go"; Args=@("run","."); Dir="$ProjectRoot\services\api-gateway"; GoEnv=$true},
|
||||
@{Title="edu-app-push-gateway"; Cmd="go"; Args=@("run","."); Dir="$ProjectRoot\services\push-gateway";GoEnv=$true},
|
||||
@{Title="edu-app-teacher-portal";Cmd="pnpm";Args=@("--filter","teacher-portal","dev"); Dir="$ProjectRoot"}
|
||||
@@ -129,11 +225,11 @@ foreach ($svc in $services) {
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " All services started in new windows. Waiting 30s for init..." -ForegroundColor Yellow
|
||||
Start-Sleep -Seconds 30
|
||||
Write-Host " All services started in new windows. Waiting 40s for init..." -ForegroundColor Yellow
|
||||
Start-Sleep -Seconds 40
|
||||
|
||||
# ===== 4. Health check =====
|
||||
Write-Host "[4/4] Health check..." -ForegroundColor Yellow
|
||||
# ===== 6. Health check =====
|
||||
Write-Host "[6/6] Health check..." -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
$healthServices = @(
|
||||
@@ -152,26 +248,30 @@ $healthServices = @(
|
||||
|
||||
$okCount = 0
|
||||
$failCount = 0
|
||||
$failedServices = @()
|
||||
foreach ($svc in $healthServices) {
|
||||
$retries = 0
|
||||
$maxRetries = 5
|
||||
$maxRetries = 3
|
||||
$success = $false
|
||||
$lastError = ""
|
||||
while ($retries -lt $maxRetries -and -not $success) {
|
||||
try {
|
||||
$null = Invoke-RestMethod -Uri $svc.Url -Method Get -TimeoutSec 3 -ErrorAction Stop
|
||||
$null = Invoke-RestMethod -Uri $svc.Url -Method Get -TimeoutSec 5 -ErrorAction Stop
|
||||
Write-Host " [OK] $($svc.Name)" -ForegroundColor Green
|
||||
$success = $true
|
||||
$okCount++
|
||||
} catch {
|
||||
$lastError = $_.Exception.Message
|
||||
$retries++
|
||||
if ($retries -lt $maxRetries) {
|
||||
Start-Sleep -Seconds 3
|
||||
Start-Sleep -Seconds 5
|
||||
}
|
||||
}
|
||||
}
|
||||
if (-not $success) {
|
||||
Write-Host " [FAIL] $($svc.Name) (failed after $maxRetries retries)" -ForegroundColor Red
|
||||
Write-Host " [FAIL] $($svc.Name) (after $maxRetries retries: $lastError)" -ForegroundColor Red
|
||||
$failCount++
|
||||
$failedServices += $svc.Name
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,13 +279,23 @@ Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host " Started: [OK] $okCount ready / [FAIL] $failCount failed" -ForegroundColor Cyan
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
|
||||
if ($failCount -gt 0) {
|
||||
Write-Host ""
|
||||
Write-Host "Failed services: $($failedServices -join ', ')" -ForegroundColor Red
|
||||
Write-Host ""
|
||||
Write-Host "Troubleshooting:" -ForegroundColor Yellow
|
||||
Write-Host " 1. Check the service window for error output" -ForegroundColor White
|
||||
Write-Host " 2. Verify dependencies: pnpm install / uv sync / go mod tidy" -ForegroundColor White
|
||||
Write-Host " 3. Re-run health check: .\scripts\health-check.ps1" -ForegroundColor White
|
||||
Write-Host " 4. Stop and retry: .\scripts\stop-all.ps1 -KillByPort then .\scripts\start-all.ps1" -ForegroundColor White
|
||||
Write-Host ""
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Next steps:" -ForegroundColor Yellow
|
||||
Write-Host " Health check: .\scripts\health-check.ps1" -ForegroundColor White
|
||||
Write-Host " CDC test: .\scripts\test-cdc.ps1" -ForegroundColor White
|
||||
Write-Host " Stop all: .\scripts\stop-all.ps1" -ForegroundColor White
|
||||
Write-Host ""
|
||||
|
||||
if ($failCount -gt 0) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user