# Job runner Postgres guarda o estado. Redis guarda o lock por usuário e uma fila de IDs. O payload da fila é somente o id do job. Estados já existentes e suficientes: `draft`, `validating`, `ready`, `queued`, `processing`, `completed`, `failed`, `expired`, `cancelled`. ## Modo `ADAPTER_JOB_MODE=worker` enfileira. `inline` só é aceito fora de produção. Produção com `inline` falha na validação de ambiente e também em `startProcess`. Falha transitória (`5xx`, exceto timeout e erros de arquivo) volta para `queued` até 3 tentativas. Timeout, validação e modelo alterado não entram em loop. O lock é liberado no `finally`. Job sem lock em `processing` é recuperado por `recoverStaleJobs`. ## Subir o piloto 1. Redis acessível em `REDIS_URL`. 2. `npm run start` para a aplicação web, com as envs de produção. 3. `npm run worker` em outro processo, com as mesmas envs de banco, storage e Redis. A limpeza de temporários roda no tick do worker. Se ela falhar, o tick seguinte continua e o erro segue para o capturador com o código `CLEANUP_FAILED`, sem conteúdo de planilha.