Inteligência Artificial

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.

Post Recentes

Erro crítico neste site: usar o modo de recuperação do WordPress 6.9

O site caiu com erro crítico depois de atualizar um plugin e o e-mail de recuperação não chegou? Force um…

11 horas atrás

NumberFormatter no PHP: R$ formatado e valor por extenso em pt-BR

O number_format não põe o R$ nem escreve o valor por extenso. Veja como usar NumberFormatter com CURRENCY e SPELLOUT…

1 dia atrás

Could not ping search engine no Magento 2: OpenSearch fora do ar

Categoria vazia e busca sem resultado no Magento 2.4.8? Teste o OpenSearch com curl, confira o bloco catalog/search do env.php…

2 dias atrás

Bookmarks da grid do Magento 2: colunas somem e o filtro fica preso

Editou o listing.xml e o admin continua com as colunas antigas ou um filtro travado? O estado da grid está…

3 dias atrás

array_chunk no PHP: processar 50 mil registros em lotes sem estourar memória

Importação morrendo com Allowed memory size exhausted? Fatie o processamento com array_chunk e, quando nem o array couber, leia o…

3 dias atrás

Unknown module in the enabled modules list: erro no Magento 2

Apagou a pasta do módulo e agora todo bin/magento morre reclamando de módulo desconhecido? A lista continua no app/etc/config.php, e…

4 dias atrás