Cuando el acompañante es un servidor
Un proceso de larga vida que tu aplicación arranca y con el que habla: puertos, arranque, salud, y las cuatro cosas que salen mal cuando el hijo vive tanto como la ventana.
Cuándo tiene sentido
La regla: si arrancar cuesta menos de un segundo y no hay estado que conservar, proceso corto. El de larga vida es para lo que carga algo pesado o mantiene algo caliente.
El canal
Dos opciones, y una es claramente mejor en escritorio:
- Un puerto de red local. Simple, funciona en todas partes, y tiene dos problemas: el puerto puede estar ocupado y cualquier otro programa de la máquina puede hablar con tu servidor. Lo segundo es lo importante y se olvida siempre.
- Un canal local del sistema —un socket de dominio o una tubería con nombre—. No usa puertos, no es accesible desde la red, y sus permisos son los del sistema de ficheros. Es lo correcto cuando la herramienta lo soporta.
Si tiene que ser un puerto:
El paso 3 merece énfasis: un servidor local sin autenticación es alcanzable desde el navegador del usuario. Es una vía real y conocida, y el testigo por sesión la cierra con diez líneas.
Saber cuándo está listo, y cuándo murió
Las dos operaciones que hay que implementar sí o sí:
// listo: sondear hasta que responda, con límiteasync fn esperar_listo(url: &str, limite: Duration) -> Result<(), Error> { let hasta = Instant::now() + limite; loop { if salud(url).await.is_ok() { return Ok(()); } if Instant::now() > hasta { return Err(Error::NoArranco); } sleep(Duration::from_millis(100)).await; }}- No supongas que está listo porque el proceso arrancó. Arrancar y estar sirviendo son cosas distintas, y entre las dos puede haber segundos.
- Y vigila que siga vivo. Un proceso hijo puede morir por su cuenta —sin memoria, un fallo interno— y tu aplicación seguiría enviándole peticiones que nadie contesta. Detectarlo y reiniciarlo una vez, avisando si vuelve a morir.
- Con un límite de reintentos: reiniciar en bucle un proceso que muere al arrancar consume la máquina del usuario sin arreglar nada.
No dejarlo huérfano
La responsabilidad más importante, y la que más se incumple:
- Matarlo en el cierre de tu aplicación. Nivel 25, y también en el cierre inesperado si el sistema lo permite.
- Y comprobar al arrancar si quedó uno de una sesión anterior. Si tu aplicación murió de golpe, puede haber un proceso huérfano; encontrarlo y matarlo antes de lanzar otro evita acumularlos.
El síntoma de no hacerlo: un usuario con cinco copias del mismo servidor consumiendo memoria, que descubre por el ventilador y atribuye —con razón— a tu aplicación.