Timeout do PHP-FPM na chamada de IA: tire do request e jogue no CLI

A tela fica girando e cai num 504 Gateway Time-out. No error.log do nginx aparece upstream timed out (110: Connection timed out) while reading response header from upstream. A API de IA levou 70 segundos para responder e o nginx desistiu aos 60, que é o padrão do fastcgi_read_timeout. Subir o max_execution_time não muda nada aqui: no Linux ele não conta o tempo parado esperando o socket responder. A saída é tirar a chamada de dentro do request.

Grave o pedido e devolva o id na hora

CREATE TABLE ia_jobs (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  entrada TEXT NOT NULL,
  saida LONGTEXT NULL,
  status ENUM('fila','rodando','pronto','erro') NOT NULL DEFAULT 'fila',
  criado_em DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  KEY idx_status_id (status, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

O controller faz um INSERT com status fila e responde o id em milissegundos. O front pergunta o status de tempos em tempos num endpoint que só faz um SELECT por id.

O worker roda no CLI, onde o tempo é seu

sudo -u www-data crontab -e

# tudo em UMA linha: crontab não aceita barra invertida para quebrar comando
* * * * * /usr/bin/flock -n /tmp/ia-worker.lock /usr/bin/php8.3 /var/www/app/worker.php >> /var/log/ia-worker.log 2>&1

No CLI o max_execution_time vale 0 por padrão, então nada mata o processo no meio. O flock -n garante que o cron do minuto seguinte desiste em vez de subir um segundo worker em cima do mesmo job. Só confira que o www-data consegue escrever no arquivo de log, senão o cron falha calado.

Insistir no timeout maior sai caro: cada request parada segura um processo do pool, e com pm.max_children = 20 bastam vinte pessoas clicando para o site inteiro parar de responder. Pior, quem se cansa aperta F5 e dispara a chamada de novo, pagando duas vezes pelo mesmo texto. Ainda vale deixar o request_terminate_timeout do pool acima do fastcgi_read_timeout para não trocar 504 por 502 sem log, mas isso é remendo, não a solução.

Dúvidas? Faça um comentário logo abaixo ou envie uma mensagem clicando aqui.

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *