Files
fn_registry/dev/issues/completed/0007b-process-manager.md
T

131 lines
3.8 KiB
Markdown

---
id: "0007b"
title: "Process manager: spawn, wait, kill, status"
status: completado
type: feature
domain: []
scope: multi-app
priority: alta
depends: []
blocks: []
related: []
created: 2026-05-17
updated: 2026-05-17
tags: []
---
# 0007b — Process manager: spawn, wait, kill, status
## Metadata
| Campo | Valor |
|-------|-------|
| **ID** | 0007b |
| **Estado** | pendiente |
| **Prioridad** | alta |
| **Tipo** | feature |
## Dependencias
| ID | Título | Estado | Requerido |
|----|--------|--------|-----------|
| 0007a | Funciones core del DAG engine | pendiente | Si |
**Bloqueada por:** `#0007a`
**Desbloquea:** `#0007e`
---
## Objetivo
Funciones impuras para gestionar procesos hijo: lanzar, esperar, matar, consultar estado. Son los bloques que el executor usara para correr cada step de un DAG.
## Contexto
- Cada step de un DAG se ejecuta como un proceso hijo (`os/exec`)
- Necesitamos captura de stdout/stderr, timeout, señales (SIGTERM/SIGKILL)
- Deben ser funciones atomicas — el executor las compone
- Dominio `infra` porque gestionan recursos del sistema
## Arquitectura
```
functions/infra/
├── process_spawn.go — NEW: lanza proceso, retorna PID + pipes
├── process_spawn.md
├── process_wait.go — NEW: espera proceso con timeout
├── process_wait.md
├── process_kill.go — NEW: envia señal a proceso (SIGTERM, SIGKILL)
├── process_kill.md
├── process_status.go — NEW: consulta estado de PID (running, exited, code)
├── process_status.md
types/infra/
├── process_handle.md — NEW: PID, stdin/stdout/stderr pipes, start_time
├── process_result.md — NEW: exit_code, stdout, stderr, duration_ms
```
### Patron pure core / impure shell
- `core/` — No aplica en este issue
- `infra/` — Todas impuras (spawn procesos, I/O con OS)
- `error_type`: `error_go_core` para todas
## Tareas
### Fase 1: Tipos
- [ ] **1.1** Definir `ProcessHandle` — pid, cmd, start_time, working_dir
- [ ] **1.2** Definir `ProcessResult` — exit_code, stdout, stderr, duration_ms, killed
### Fase 2: Funciones
- [ ] **2.1** `process_spawn` — ejecuta comando con args, env, working_dir. Retorna ProcessHandle. No bloquea.
- [ ] **2.2** `process_wait` — espera a que el proceso termine o timeout. Retorna ProcessResult.
- [ ] **2.3** `process_kill` — envia SIGTERM, espera grace period, luego SIGKILL si sigue vivo
- [ ] **2.4** `process_status` — consulta si el PID sigue corriendo, retorna estado
### Fase 3: Tests
- [ ] **3.1** Tests: spawn+wait de `echo hello`, timeout con `sleep 999`, kill de proceso largo
- [ ] **3.2** Tests: captura correcta de stdout/stderr, exit codes no-zero
### Fase 4: Cleanup
- [ ] `fn index` y verificar IDs
- [ ] Verificar error_type en todas las funciones impuras
---
## Ejemplo de uso
```go
handle, err := process_spawn(ProcessSpawnInput{
Command: "python3",
Args: []string{"script.py", "--flag"},
Env: []string{"API_KEY=xxx"},
WorkingDir: "/home/lucas/project",
})
result, err := process_wait(handle, 30*time.Second) // timeout 30s
// result.ExitCode == 0, result.Stdout == "output..."
// O matar si tarda demasiado
process_kill(handle, 5*time.Second) // SIGTERM, 5s grace, luego SIGKILL
```
## Decisiones de diseno
- **Spawn no bloquea**: retorna handle inmediatamente, wait es separado — permite al executor lanzar steps en paralelo
- **Kill con grace period**: SIGTERM primero, espera, SIGKILL si no murio — comportamiento estandar de process managers
- **Stdout/stderr como strings**: para steps cortos. Para steps con output grande, futuro: streaming a archivo
## Criterios de aceptacion
- [ ] Spawn y wait funcionan con comandos reales
- [ ] Timeout mata el proceso correctamente
- [ ] Kill con grace period funciona
- [ ] Exit codes se capturan correctamente
- [ ] Tests pasan
- [ ] Indexado en registry.db