fix(infra): resolve NestJS dist build and Prometheus target issues
Some checks failed
CI / quality-go (push) Failing after 5s
CI / quality-proto (push) Failing after 3s
CI / deploy (push) Has been skipped
CI / quality-ts (push) Failing after 50s

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:
SpecialX
2026-07-09 15:12:15 +08:00
parent b72c8d81d4
commit f1e466a772
16 changed files with 267 additions and 55 deletions

View File

@@ -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
}