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>&1No 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.