src/public/Orchestration/Submit-AitherJob.ps1
|
#Requires -Version 7.0 <# .SYNOPSIS Submits an async job to the AitherOS Genesis orchestrator. .DESCRIPTION Dispatches a long-running task to the Genesis job queue for asynchronous execution. Returns a job ID that can be polled for status. Supports playbook submission, agent dispatch, and arbitrary task payloads. This enables non-blocking orchestration: submit a job, continue working, and check results later. .PARAMETER Task Description of the task to execute. .PARAMETER Type Job type: playbook, agent, script, or custom. Defaults to custom. .PARAMETER Playbook Name of a playbook to run asynchronously (sets Type to 'playbook'). .PARAMETER Agent Agent to dispatch (sets Type to 'agent'). E.g., 'demiurge', 'athena'. .PARAMETER Parameters Hashtable of parameters to pass to the job. .PARAMETER Priority Job priority: low, normal, high, critical. Defaults to normal. .PARAMETER GenesisUrl URL of the Genesis service. Defaults to http://localhost:8001. .PARAMETER Poll After submission, poll for completion instead of returning immediately. Shows a progress indicator. .PARAMETER PollInterval Poll interval in seconds. Defaults to 5. .PARAMETER PollTimeout Maximum time to poll in seconds. Defaults to 600 (10 minutes). .EXAMPLE Submit-AitherJob -Playbook "deploy-prod" -Parameters @{ Environment = "production" } # Submit a deployment playbook asynchronously .EXAMPLE Submit-AitherJob -Agent "demiurge" -Task "Refactor auth module" -Priority high # Submit an agent task at high priority .EXAMPLE $job = Submit-AitherJob -Task "Run full test suite" -Type script -Poll # Submit and wait for completion .EXAMPLE Submit-AitherJob -Task "Generate monthly report" | ForEach-Object { $_.job_id } # Get job ID for later status check .NOTES Category: Orchestration Dependencies: AitherOS Genesis (port 8001) Platform: Windows, Linux, macOS #> function Submit-AitherJob { [CmdletBinding()] param( [Parameter(Position = 0)] [string]$Task, [Parameter()] [ValidateSet('playbook', 'agent', 'script', 'custom')] [string]$Type = 'custom', [Parameter()] [string]$Playbook, [Parameter()] [string]$Agent, [Parameter()] [hashtable]$Parameters = @{}, [Parameter()] [ValidateSet('low', 'normal', 'high', 'critical')] [string]$Priority = 'normal', [Parameter()] [string]$GenesisUrl, [Parameter()] [switch]$Poll, [Parameter()] [int]$PollInterval = 5, [Parameter()] [int]$PollTimeout = 600 ) if (-not $GenesisUrl) { $ctx = Get-AitherLiveContext $GenesisUrl = if ($ctx.OrchestratorURL) { $ctx.OrchestratorURL } else { "http://localhost:8001" } } # Auto-set type from parameters if ($Playbook) { $Type = 'playbook'; if (-not $Task) { $Task = "Run playbook: $Playbook" } } if ($Agent) { $Type = 'agent'; if (-not $Task) { $Task = "Agent dispatch: $Agent" } } if (-not $Task) { Write-Error "Task description is required. Use -Task, -Playbook, or -Agent." return } # Build job payload $body = @{ task = $Task type = $Type priority = $Priority parameters = $Parameters source = 'aitherzero-cli' submitted = (Get-Date).ToUniversalTime().ToString("o") } if ($Playbook) { $body.playbook = $Playbook } if ($Agent) { $body.agent = $Agent } try { Write-Host "`n Submitting job: $Task" -ForegroundColor Cyan Write-Host " Type: $Type | Priority: $Priority" -ForegroundColor DarkGray $result = Invoke-RestMethod -Uri "$GenesisUrl/api/jobs/submit" ` -Method POST -Body ($body | ConvertTo-Json -Depth 5 -Compress) ` -ContentType 'application/json' -TimeoutSec 15 -ErrorAction Stop $jobId = if ($result.job_id) { $result.job_id } elseif ($result.id) { $result.id } else { 'unknown' } Write-Host " Job submitted: $jobId" -ForegroundColor Green # Report to Strata if (Get-Command Send-AitherStrata -ErrorAction SilentlyContinue) { Send-AitherStrata -EventType 'job-submitted' -Data @{ job_id = $jobId type = $Type priority = $Priority task = $Task } } if (-not $Poll) { return $result } # Poll for completion Write-Host " Polling for completion (interval: ${PollInterval}s, timeout: ${PollTimeout}s)" -ForegroundColor DarkGray $startTime = [DateTime]::UtcNow $spinChars = @('|', '/', '-', '\') $spinIdx = 0 while (([DateTime]::UtcNow - $startTime).TotalSeconds -lt $PollTimeout) { Start-Sleep -Seconds $PollInterval try { $status = Invoke-RestMethod -Uri "$GenesisUrl/api/jobs/$jobId/status" ` -Method GET -TimeoutSec 10 -ErrorAction Stop $jobStatus = if ($status.status) { $status.status } else { 'unknown' } $spin = $spinChars[$spinIdx % 4] $spinIdx++ $elapsed = [math]::Round(([DateTime]::UtcNow - $startTime).TotalSeconds) Write-Host "`r $spin $jobStatus (${elapsed}s)" -NoNewline -ForegroundColor DarkGray if ($jobStatus -in @('completed', 'success', 'failed', 'error', 'cancelled')) { Write-Host "" $color = if ($jobStatus -in @('completed', 'success')) { 'Green' } else { 'Red' } Write-Host " Job $jobStatus" -ForegroundColor $color if ($status.result) { return $status.result } return $status } } catch { Write-Verbose "Poll error: $_" } } Write-Warning " Poll timeout reached ($PollTimeout s). Job $jobId may still be running." Write-Warning " Check status: Invoke-RestMethod '$GenesisUrl/api/jobs/$jobId/status'" return $result } catch { Write-Warning "Job submission failed: $_" Write-Warning "Is Genesis running at $GenesisUrl?" return $null } } |