86 lines
4.4 KiB
PowerShell
86 lines
4.4 KiB
PowerShell
<# Load project .env, then prepare independent services in separate processes. #>
|
|
$ErrorActionPreference = 'Stop'
|
|
. "$PSScriptRoot\output.ps1"
|
|
$script:TravelSource = 'init'
|
|
trap { Write-TravelLog -Level ERROR -Message $_.Exception.Message; throw }
|
|
$initTimer = [Diagnostics.Stopwatch]::StartNew()
|
|
& "$PSScriptRoot\env.ps1"
|
|
Write-TravelLog -Message 'Environment loaded from .env.'
|
|
|
|
# FlyAI CLI is managed by the default Node/npm environment.
|
|
if (-not (Get-Command flyai -ErrorAction SilentlyContinue)) {
|
|
& npm.cmd install --global @fly-ai/flyai-cli@1.0.16
|
|
if ($LASTEXITCODE -ne 0) { throw "FlyAI npm install failed with exit code $LASTEXITCODE." }
|
|
Write-TravelLog -Message 'FlyAI CLI installed globally.'
|
|
} else {
|
|
Write-TravelLog -Message 'FlyAI CLI is ready.'
|
|
}
|
|
|
|
|
|
# Sync the project key to FlyAI's own configuration store.
|
|
if (-not [string]::IsNullOrWhiteSpace($env:FLYAI_API_KEY)) {
|
|
& flyai config set FLYAI_API_KEY $env:FLYAI_API_KEY | Out-Null
|
|
if ($LASTEXITCODE -ne 0) { throw "FlyAI configuration failed with exit code $LASTEXITCODE." }
|
|
Write-TravelLog -Message 'FlyAI API key configured from .env.'
|
|
}
|
|
|
|
# Process isolation prevents Douyin's temporary environment variables affecting Xiaohongshu.
|
|
$initJobs = @()
|
|
$initDrainedJobs = @{}
|
|
$initDouyinExitCode = 0
|
|
try {
|
|
foreach ($initService in @('xiaohongshu')) {
|
|
$initJobs += Start-Job -Name $initService -ScriptBlock {
|
|
param($scriptPath)
|
|
$ErrorActionPreference = 'Stop'
|
|
Set-Location -LiteralPath (Split-Path (Split-Path $scriptPath -Parent) -Parent)
|
|
& $scriptPath
|
|
} -ArgumentList (Join-Path $PSScriptRoot "$initService.ps1")
|
|
}
|
|
Write-TravelLog -Message 'Starting initialization tasks: xiaohongshu, douyin (parallel).'
|
|
# Inherit the console directly so uv and Python retain their native progress bars.
|
|
# A separate process still isolates Douyin's environment from the other service.
|
|
$initPowerShell = (Get-Process -Id $PID).Path
|
|
$initDouyinTimer = [Diagnostics.Stopwatch]::StartNew()
|
|
& $initPowerShell -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot 'douyin.ps1')
|
|
$initDouyinExitCode = $LASTEXITCODE
|
|
$initDouyinLevel = if ($initDouyinExitCode -eq 0) { 'INFO' } else { 'ERROR' }
|
|
Write-TravelLog -Level $initDouyinLevel -Message ('task=douyin exit_code={0} duration={1:F1}s' -f $initDouyinExitCode, $initDouyinTimer.Elapsed.TotalSeconds)
|
|
while ($true) {
|
|
foreach ($initJob in $initJobs) {
|
|
if ($initDrainedJobs.ContainsKey($initJob.Id)) { continue }
|
|
$initTerminal = $initJob.State -in @('Completed', 'Failed', 'Stopped')
|
|
Receive-Job -Job $initJob -ErrorAction Continue 2>&1 3>&1 4>&1 5>&1 | Write-TravelRecord -Source $initJob.Name
|
|
if ($initTerminal) { $initDrainedJobs[$initJob.Id] = $true }
|
|
}
|
|
$initPending = @($initJobs | Where-Object { $_.State -in @('NotStarted', 'Running') })
|
|
if ($initPending.Count -eq 0) { break }
|
|
Wait-Job -Job $initPending -Any -Timeout 1 | Out-Null
|
|
}
|
|
# Drain output produced between the last receive and job completion.
|
|
foreach ($initJob in $initJobs) {
|
|
if (-not $initDrainedJobs.ContainsKey($initJob.Id)) {
|
|
Receive-Job -Job $initJob -ErrorAction Continue 2>&1 3>&1 4>&1 5>&1 | Write-TravelRecord -Source $initJob.Name
|
|
}
|
|
$initDuration = if ($initJob.PSEndTime -and $initJob.PSBeginTime) {
|
|
($initJob.PSEndTime - $initJob.PSBeginTime).TotalSeconds
|
|
} else { 0 }
|
|
$initLevel = if ($initJob.State -eq 'Completed') { 'INFO' } else { 'ERROR' }
|
|
Write-TravelLog -Level $initLevel -Message ('task={0} status={1} duration={2:F1}s' -f $initJob.Name, $initJob.State, $initDuration)
|
|
}
|
|
$initFailed = @($initJobs | Where-Object { $_.State -ne 'Completed' })
|
|
$initFailedNames = @($initFailed | ForEach-Object { $_.Name })
|
|
if ($initDouyinExitCode -ne 0) { $initFailedNames += 'douyin' }
|
|
if ($initFailedNames.Count -gt 0) {
|
|
throw "Initialization failed: $($initFailedNames -join ', '). See the errors above."
|
|
}
|
|
Write-TravelLog -Message ('Initialization completed in {0:F1}s. Run cpa to continue.' -f $initTimer.Elapsed.TotalSeconds)
|
|
} finally {
|
|
foreach ($initJob in $initJobs) {
|
|
if ($initJob.State -in @('NotStarted', 'Running', 'Blocked')) {
|
|
Stop-Job -Job $initJob -ErrorAction SilentlyContinue
|
|
}
|
|
Remove-Job -Job $initJob -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|