Ping periódico no servidor WebSocket
TLDR: adiciona ping periódico do servidor para manter conexões WebSocket ociosas vivas, evitando que o timeout de keep-alive do Gunicorn as derrube.
Contexto
O worker do Gunicorn usa --keep-alive 30, o que significa que conexões WebSocket ociosas podem ser derrubadas após ~30 segundos. O loop principal em _ws_handler bloqueava indefinidamente em await ws.receive_json(), então não conseguia enviar pings enquanto esperava mensagens do cliente. Quando o usuário abria o chat e não digitava por 30s, a conexão caía silenciosamente.
O cliente mobile já reconecta automaticamente (onion-mobile PR #83), mas um ping do lado do servidor evita reconexões desnecessárias e mantém a conexão viva durante a janela de resposta da LLM.
Objetivos
- Enviar um frame
{"type": "ping"}para o cliente a cada 20 segundos de ociosidade - Detectar conexões mortas do lado do servidor (cliente não responde) e fechá-las de forma limpa
- Não interferir no fluxo normal de mensagens
Fora de escopo
- Medir latência round-trip do ping/pong
- Intervalo de ping configurável via variável de ambiente (20s fixo é suficiente)
- Mudanças no cliente mobile (tratado na PR #83 do onion-mobile)
Mudanças
onion_chat/controllers/v2/websocket_controller.py
Substitui o await ws.receive_json() bloqueante por uma chamada asyncio.wait_for(..., timeout=20) dentro do loop:
- Se o timeout expirar sem mensagem → envia
{"type": "ping"}e volta a esperar - Se
asyncio.TimeoutErrorfor lançado com um ping já pendente sem pong → fecha a conexão (cliente morto) - Se chegar uma mensagem
{"type": "pong"}→ zera o estado de ping pendente e volta a esperar (não processa como mensagem de chat) - Todo o tratamento de mensagens existente permanece inalterado
Como verificar
- Conectar em
/ws/chatcom um token válido - Não enviar nenhuma mensagem por 25 segundos — confirmar que chega um frame
{"type": "ping"} - Responder com
{"type": "pong"}— confirmar que a conexão permanece viva - Não responder ao ping por mais 20s — confirmar que o servidor fecha a conexão
- Confirmar que o fluxo normal de chat (enviar mensagem, receber resposta) continua funcionando sem interrupção
Documentação
Nenhuma mudança de documentação adicional necessária.