Files
INFRAESTRUCTURA/omniroute/omniroute_watchdog.ps1

175 lines
6.3 KiB
PowerShell

<#
.SYNOPSIS
Vigilante (watchdog) de OmniRoute: garantiza que el servidor local este SIEMPRE arriba.
.DESCRIPTION
OmniRoute escucha en http://127.0.0.1:20128 y tarda ~60 s en quedar listo.
Este vigilante:
- Comprueba el puerto 20128 periodicamente.
- Si no hay proceso, arranca el servidor en segundo plano (oculto, desde un
directorio neutro para no contaminarse con .env de repositorios).
- Si hay proceso pero no responde tras el tiempo de arranque, lo mata y lo relanza.
Se lanza al iniciar sesion mediante la tarea programada "OmniRoute Watchdog".
.PARAMETER Once
Comprueba/arranca una sola vez, espera a que responda y sale (para pruebas).
.PARAMETER IntervalSeconds
Segundos entre comprobaciones del bucle de vigilancia (por defecto 120).
.PARAMETER StartupTimeoutSeconds
Segundos maximos de espera a que OmniRoute responda antes de considerarlo colgado.
.PARAMETER UseTray
Arranca OmniRoute con icono en la bandeja del sistema (por defecto NO, para maxima
fiabilidad en el arranque desatendido).
.NOTES
Repo: biblioteca_negocio_prolongo. Regla 24 no aplica (no toca NET/VB/4GL).
#>
[CmdletBinding()]
param(
[switch]$Once,
[int]$IntervalSeconds = 120,
[int]$StartupTimeoutSeconds = 180,
[switch]$UseTray
)
$ErrorActionPreference = 'SilentlyContinue'
# --- Configuracion ---------------------------------------------------------
$OmniHost = '127.0.0.1'
$Port = 20128
$NodeExe = 'C:\Program Files\nodejs\node.exe'
$OmniRouteMjs = Join-Path $env:APPDATA 'npm\node_modules\omniroute\bin\omniroute.mjs'
$WorkDir = $env:USERPROFILE # directorio neutro (sin .env de repos)
$LogDir = Join-Path $env:USERPROFILE '.omniroute'
$LogFile = Join-Path $LogDir 'watchdog.log'
$MaxLogBytes = 1MB
# --- Utilidades ------------------------------------------------------------
function Write-Log {
param([string]$Message, [string]$Level = 'INFO')
$line = '{0} [{1}] {2}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Level, $Message
if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Path $LogDir -Force | Out-Null }
if ((Test-Path $LogFile) -and ((Get-Item $LogFile).Length -gt $MaxLogBytes)) {
Move-Item -LiteralPath $LogFile -Destination "$LogFile.1" -Force
}
Add-Content -LiteralPath $LogFile -Value $line -Encoding UTF8
}
function Resolve-NodeExe {
if (Test-Path $NodeExe) { return $NodeExe }
$cmd = Get-Command node -ErrorAction SilentlyContinue
if ($cmd) { return $cmd.Source }
return $NodeExe
}
function Test-OmniRoutePort {
$client = New-Object System.Net.Sockets.TcpClient
try {
$iar = $client.BeginConnect($OmniHost, $Port, $null, $null)
if ($iar.AsyncWaitHandle.WaitOne(2000)) {
$client.EndConnect($iar)
return $true
}
return $false
} catch {
return $false
} finally {
try { $client.Close() } catch { }
}
}
function Get-OmniRouteProcesses {
Get-CimInstance Win32_Process -Filter "Name='node.exe'" -ErrorAction SilentlyContinue |
Where-Object {
$_.CommandLine -and
($_.CommandLine -like '*omniroute*') -and
($_.CommandLine -like '*serve*')
}
}
function Start-OmniRouteServer {
$node = Resolve-NodeExe
if (-not (Test-Path $OmniRouteMjs)) {
Write-Log "No se encuentra omniroute.mjs en $OmniRouteMjs" 'ERROR'
return
}
$argList = @("`"$OmniRouteMjs`"", 'serve', '--no-open')
if ($UseTray) { $argList += '--tray' } else { $argList += '--no-tray' }
Start-Process -FilePath $node `
-ArgumentList $argList `
-WorkingDirectory $WorkDir `
-WindowStyle Hidden
Write-Log "Servidor OmniRoute lanzado (tray=$([bool]$UseTray))."
}
function Wait-OmniRouteUp {
param([int]$TimeoutSeconds)
for ($i = 0; $i -lt $TimeoutSeconds; $i += 3) {
Start-Sleep -Seconds 3
if (Test-OmniRoutePort) { return $true }
}
return $false
}
# --- Bloqueo de instancia unica -------------------------------------------
$mutex = New-Object System.Threading.Mutex($false, 'Local\OmniRouteWatchdog')
if (-not $mutex.WaitOne(0)) {
Write-Log 'Ya hay otro vigilante en ejecucion. Saliendo.' 'WARN'
exit 0
}
# --- Modo puntual (-Once) --------------------------------------------------
if ($Once) {
if (Test-OmniRoutePort) {
Write-Log "Comprobacion puntual: OmniRoute ya responde en $Port." 'OK'
exit 0
}
$procs = @(Get-OmniRouteProcesses)
if ($procs.Count -eq 0) {
Write-Log 'Comprobacion puntual: OmniRoute caido. Arrancando...' 'WARN'
Start-OmniRouteServer
} else {
Write-Log "Comprobacion puntual: proceso presente (PID $($procs[0].ProcessId)), esperando puerto..." 'WARN'
}
if (Wait-OmniRouteUp -TimeoutSeconds $StartupTimeoutSeconds) {
Write-Log "Comprobacion puntual: OmniRoute arriba en $Port." 'OK'
exit 0
}
Write-Log "Comprobacion puntual: OmniRoute NO respondio en $StartupTimeoutSeconds s." 'ERROR'
exit 1
}
# --- Bucle de vigilancia ---------------------------------------------------
Write-Log 'Vigilante de OmniRoute iniciado.'
$downSince = $null
while ($true) {
if (Test-OmniRoutePort) {
if ($downSince) { Write-Log "OmniRoute vuelve a responder en $Port." 'OK' }
$downSince = $null
}
else {
$procs = @(Get-OmniRouteProcesses)
if ($procs.Count -gt 0) {
if (-not $downSince) {
$downSince = Get-Date
Write-Log "Proceso OmniRoute presente (PID $($procs[0].ProcessId)) pero $Port aun no responde; esperando arranque (~60 s)..."
}
elseif (((Get-Date) - $downSince).TotalSeconds -gt $StartupTimeoutSeconds) {
Write-Log "OmniRoute lleva mas de $StartupTimeoutSeconds s sin responder. Matando procesos colgados y relanzando." 'WARN'
$procs | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
Start-Sleep -Seconds 3
Start-OmniRouteServer
$downSince = Get-Date
}
}
else {
Write-Log "OmniRoute CAIDO (puerto $Port cerrado). Arrancando servidor..." 'WARN'
Start-OmniRouteServer
$downSince = Get-Date
}
}
Start-Sleep -Seconds $IntervalSeconds
}