# Parallel comprehensive validation: travel / semantic / profile as separate jobs (sequential invoke, split reports for CI). # Usage: # cd d:\ylrz_saas_new\java\scripts # .\run_lobster_comprehensive_parallel.ps1 -CompanyId 338 -TenantId 33 # .\run_lobster_comprehensive_parallel.ps1 -SkipStress -SkipBuild -SkipRestart param( [string]$ApiBase = "http://127.0.0.1:8006", [int]$CompanyId = 338, [int]$TenantId = 33, [string]$OpsSecret = "lobster-dev-ops", [string]$ReportDir = "", [switch]$SkipBuild, [switch]$SkipRestart, [switch]$SkipStress, [string]$JavaHome = "" ) $ErrorActionPreference = "Stop" $repoRoot = Split-Path $PSScriptRoot -Parent if ([string]::IsNullOrWhiteSpace($ReportDir)) { $ReportDir = Join-Path $repoRoot "validation-reports" } New-Item -ItemType Directory -Force -Path $ReportDir | Out-Null if ([string]::IsNullOrWhiteSpace($JavaHome)) { if ($env:JAVA_HOME) { $JavaHome = $env:JAVA_HOME } elseif (Test-Path "D:\jdk-17.0.2") { $JavaHome = "D:\jdk-17.0.2" } } if (-not $SkipBuild -or -not $SkipRestart) { $ciArgs = @{ ApiBase = $ApiBase CompanyId = $CompanyId TenantId = $TenantId OpsSecret = $OpsSecret JavaHome = $JavaHome SkipBuild = $SkipBuild.IsPresent SkipRestart = $SkipRestart.IsPresent SkipStress = $true } & (Join-Path $PSScriptRoot "run_lobster_travel_validation_ci.ps1") @ciArgs if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } } $h = @{ "Content-Type" = "application/json" "X-Lobster-Ops-Secret" = $OpsSecret } function Invoke-LobsterJob { param( [string]$Name, [string]$Uri, [string]$OutFile ) Write-Host " start $Name ..." -ForegroundColor Yellow $sw = [System.Diagnostics.Stopwatch]::StartNew() try { $r = Invoke-RestMethod -Method POST -Uri $Uri -Headers $h -TimeoutSec 900 $r | ConvertTo-Json -Depth 30 | Out-File -FilePath $OutFile -Encoding utf8 $passed = $r.passed Write-Host " done $Name passed=$passed ($([math]::Round($sw.Elapsed.TotalSeconds,1))s)" -ForegroundColor $(if ($passed) { "Green" } else { "Red" }) return [PSCustomObject]@{ Name = $Name; Passed = $passed; Seconds = $sw.Elapsed.TotalSeconds; File = $OutFile; Failures = $r.failures } } catch { Write-Host " FAIL $Name : $($_.Exception.Message)" -ForegroundColor Red return [PSCustomObject]@{ Name = $Name; Passed = $false; Seconds = $sw.Elapsed.TotalSeconds; File = $OutFile; Failures = @($_.Exception.Message) } } } Write-Host "=== Lobster Split Validation (travel + semantic + profile) ===" -ForegroundColor Cyan $stressQ = if ($SkipStress) { "false" } else { "true" } $totalSw = [System.Diagnostics.Stopwatch]::StartNew() $results = @( (Invoke-LobsterJob -Name "travel-full" ` -Uri "$ApiBase/api/lobster/admin/validation/travel-full/$CompanyId?tenantId=$TenantId&includeStress=$stressQ" ` -OutFile (Join-Path $ReportDir "parallel-travel.json")), (Invoke-LobsterJob -Name "semantic-full" ` -Uri "$ApiBase/api/lobster/admin/validation/semantic-context/$CompanyId?tenantId=$TenantId&mode=full" ` -OutFile (Join-Path $ReportDir "parallel-semantic.json")), (Invoke-LobsterJob -Name "profile-full" ` -Uri "$ApiBase/api/lobster/admin/validation/profile-domain-full/$CompanyId?tenantId=$TenantId" ` -OutFile (Join-Path $ReportDir "parallel-profile.json")) ) $allPassed = ($results | Where-Object { -not $_.Passed }).Count -eq 0 $summary = [ordered]@{ companyId = $CompanyId tenantId = $TenantId includeStress = (-not $SkipStress) startedAt = (Get-Date -Format "yyyy-MM-dd HH:mm:ss") durationSec = [math]::Round($totalSw.Elapsed.TotalSeconds, 1) allPassed = $allPassed jobs = $results } $summaryPath = Join-Path $ReportDir "parallel-summary.json" $summary | ConvertTo-Json -Depth 8 | Out-File -FilePath $summaryPath -Encoding utf8 Write-Host "" Write-Host "Summary: allPassed=$allPassed total=$($summary.durationSec)s -> $summaryPath" -ForegroundColor $(if ($allPassed) { "Green" } else { "Red" }) if (-not $allPassed) { foreach ($r in $results | Where-Object { -not $_.Passed }) { Write-Host " FAILED: $($r.Name)" -ForegroundColor Red if ($r.Failures) { $r.Failures | ForEach-Object { Write-Host " $_" } } } exit 1 } exit 0