start_course_demo.ps1 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #Requires -Version 7.0
  2. param(
  3. [ValidateSet('Prepare', 'Stop')]
  4. [string] $Action = 'Prepare',
  5. [ValidatePattern('^[a-zA-Z0-9][a-zA-Z0-9_-]{0,47}$')]
  6. [string] $Session,
  7. [ValidateRange(1, 180)]
  8. [int] $DurationMinutes = 180
  9. )
  10. $ErrorActionPreference = 'Stop'
  11. $demoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
  12. $demoDirectory = Join-Path $demoRoot '.work/course-demo'
  13. $demoScript = Join-Path $PSScriptRoot 'prepare_course_demo.py'
  14. $demoPython = Join-Path $demoRoot '.venv/Scripts/python.exe'
  15. $demoProcessFile = Join-Path $demoDirectory 'sync-process.json'
  16. function Stop-DemoSync {
  17. if (-not (Test-Path -LiteralPath $demoProcessFile)) { return }
  18. $record = Get-Content -LiteralPath $demoProcessFile -Raw | ConvertFrom-Json
  19. $process = Get-Process -Id $record.pid -ErrorAction SilentlyContinue
  20. if ($null -eq $process) { return }
  21. $details = Get-CimInstance Win32_Process -Filter "ProcessId = $($record.pid)"
  22. # 仅停止本入口登记且创建时间一致的同步进程,防止 PID 被其他程序复用。
  23. if ($process.StartTime.ToUniversalTime().Ticks -ne [long]$record.started_ticks -or
  24. $null -eq $details.CommandLine -or -not $details.CommandLine.Contains($demoScript)) {
  25. throw '订单同步进程身份检查失败,请检查进程记录。'
  26. }
  27. $process.Kill($true)
  28. if (-not $process.WaitForExit(10000)) { throw '订单同步进程未在十秒内停止。' }
  29. }
  30. Push-Location $demoRoot
  31. try {
  32. if ($Action -eq 'Stop') {
  33. Stop-DemoSync
  34. Write-Output '课程订单同步已停止,课程数据保留。'
  35. return
  36. }
  37. if (-not (Test-Path -LiteralPath $demoPython)) { throw '请准备项目 Python 环境。' }
  38. if (-not $Session) { $Session = Get-Date -Format 'yyyyMMdd-HHmmss-fff' }
  39. $env:PYTHONUTF8 = '1'
  40. $env:PYTHONIOENCODING = 'utf-8'
  41. & $demoPython $demoScript prepare --session $Session
  42. if ($LASTEXITCODE -ne 0) { throw '课程订单准备失败。' }
  43. # 履约进程读取已登记的专用 OMS 凭据;Compose 保留现有数据库与其他服务。
  44. $env:ZHIFU_RUNTIME_ENV = (Resolve-Path '.work/runtime.env').Path
  45. $env:ZHIFU_MODEL_PATH = (Resolve-Path '.work/models').Path
  46. docker compose -f compose.runtime.yaml up -d --no-deps fulfillment
  47. if ($LASTEXITCODE -ne 0) { throw '履约进程配置加载失败。' }
  48. Stop-DemoSync
  49. $durationSeconds = $DurationMinutes * 60
  50. $arguments = @(('"' + $demoScript + '"'), 'sync', '--session', $Session,
  51. '--duration-seconds', "$durationSeconds", '--interval-seconds', '60')
  52. $stdout = Join-Path $demoDirectory "$Session-sync.stdout.log"
  53. $stderr = Join-Path $demoDirectory "$Session-sync.stderr.log"
  54. $process = Start-Process -FilePath $demoPython -ArgumentList $arguments `
  55. -WorkingDirectory $demoRoot -WindowStyle Hidden -PassThru `
  56. -RedirectStandardOutput $stdout -RedirectStandardError $stderr
  57. @{pid = $process.Id; started_ticks = $process.StartTime.ToUniversalTime().Ticks;
  58. session = $Session; duration_seconds = $durationSeconds; interval_seconds = 60;
  59. stdout = $stdout; stderr = $stderr} |
  60. ConvertTo-Json | Set-Content -LiteralPath $demoProcessFile -Encoding utf8
  61. if ($process.WaitForExit(3000)) {
  62. Get-Content -LiteralPath $stderr
  63. throw '订单同步进程提前结束。'
  64. }
  65. Write-Output "课程 $Session 已准备;每 60 秒从 OMS 同步一次,最长 $DurationMinutes 分钟。"
  66. Write-Output "本次账户及订单:$demoDirectory/active.json"
  67. } finally {
  68. Pop-Location
  69. }