Executando verificação de segurança...
Em resposta a [Não disponível]
3

Quase nunca utilizaremos o Long Polling para qualquer projeto.

Como você disse, o Long Polling foi uma tática usada para comunicar um cliente de alterações antes do websocket, porém existe opções melhores atualmente.

O Server Sent Events é a alternativa perfeita para quando não é necessário a complexidade de um websocket, mas ao mesmo tempo você quer manter a comunicação em tempo real

Ele funciona definindo um tipo de resposta como "text/event-stream" e enviando o conteúdo periodicamente no seguinte formato

event: NOME_DO_EVENTO
data: CONTEUDO_JSON

Com isso não há necessidade de fechar a conexão e abrir um novo request

<?php

// Headers necessários para o SSE
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');

// Desativa a compactação Gzip no servidor para evitar buffer de eventos
if (ini_get('zlib.output_compression')) {
    ini_set('zlib.output_compression', 'Off');
}

// Desativa o tempo limite do PHP
set_time_limit(0);

while (true) {
    $newMessage = getNewMessages();

    if ($newMessage) {
        // Formata os dados para o SSE
        $data = json_encode($newMessage);

        // Envia o evento 'messageCreate' para o cliente
        echo "event: messageCreate\n";
        echo "data: {$data}\n\n";

        // Libera o buffer de saída do servidor para garantir que o evento seja enviado
        ob_flush();
        flush();
    }
    sleep(1);
}

?>

Essa alternativa é muito melhor que o Long Polling, sendo usada na API oficial do Docker ou até mesmo no próprio ChatGPT, que retorna sua resposta usando o SSE.

Contudo, é importante salientar: PHP não foi feito para trabalhar com conexões permanentes, usem sempre alguma outra linguagem para esses cenários

Carregando publicação patrocinada...
4

O significado correto de SSE é Server-Sent Events, não Single Sent Events.
Uma limitação importante de citar no uso de SSE é que ela entra na limitação de conexões do browser (geralmente 6) para a mesma fonte. Isso pode ser muito importante e limitador dependendo do tipo de aplicação que você esteja servindo.
Por exemplo, em uma aplicação que meu time fez, composta de várias páginas individuais com análises de diferentes produtos e indicadores, fizemos a implementação de notificações usando SSE.
Como fizemos os testes somente com uma aba aberta tudo parecido correr normalmente e a alteração subiu pra produção.
Passamos então a receber vários reports de que a página não carregava, ficava em branco. Acessamos remotamente a máquina de um dos usuários e verificamos que haviam várias janelas e abas abertas da mesma página, algumas carregaram outras ficaram em branco.
Foi quando caiu a ficha, estávamos batendo no limite de conexões do navegador.
Conforme disse antes, em geral essa limitação é igual a 6. Se abrissemos 5 janelas ou abas da mesma aplicação elas carregavam, porém a sexta ficava em branco (mais detalhes a seguir).
Além disso notamos também que a medida que abríamos mais instâncias da mesma página, o carregamento ficava mais lento.
Analisando a aba de conexões da ferramenta para desenvolvedores, constatamos que na segunda instância, era aberta uma conexão sse e o browser usava outras 4 simultâneas pra fazer o fetch dos recursos. Na terceira havia uma coleção sse aberta e o browser usava outras 3 simultâneas para buscar recursos no servidor. Quando estávamos na sexta instância, o browser mantinha a conexão sse aberta e não buscava mais nenhum recurso do servidor após a conexão estabelecia, ficando a página vazia. O limite tinha sido atingido - 1 conexão sse aberta em cada uma das 6 abas - e então o browser ficava esperando que uma das conexões fosse fechada para requisitar os recursos necessários ao servidor.
A solução que encontramos foi fazer a página detectar se a janela era ou não a que estava ativa e fazer a re-conexão/desconexão de acordo com isso. Deu muito trabalho pra acertar tudo mas no final está funcionando corretamente.