Manter o chat ativo quando o telemóvel adormece
O agente da Mythex pode trabalhar durante minutos num só pedido, e pode muito bem estar a acompanhar a partir de um telemóvel — que bloqueia, muda de app e troca de rede enquanto trabalha. Dois erros estragavam isso. Num, o chat tratava cada sinal de «a página está visível outra vez» como prova de que a ligação tinha morrido, e ficava em loop até parar em «A ligar…». No outro, um telemóvel que adormeceu durante a primeira resposta de um chat novo voltava a mostrar apenas as primeiras peças dela, até um refresh manual. Ambos estão corrigidos.
Como o chat acompanha um turno em curso
Enquanto o agente trabalha, o chat mantém aberto um streaming a partir dos nossos servidores: cada passo — um pensamento, uma chamada de ferramenta, um pedaço da resposta — chega como um evento. Se o streaming cair, o chat volta a ligar-se e o servidor repete os eventos recentes a partir de um buffer que guarda os últimos 120 segundos. Quando o turno termina, o chat também pede ao servidor o histórico guardado e reconcilia o que mostrava com o que foi guardado. Esse último passo apanha tudo o que o streaming tenha perdido.
Para distinguir uma ligação viva de uma morta quando nada está a acontecer, o servidor envia um pequeno «ping» a cada 15 segundos.
Erro 1: acordar matava um streaming saudável
Os browsers avisam uma página quando ela volta a ficar visível: depois de mudar de separador, depois de desbloquear o ecrã. Nós usávamos isso como sinal para verificar a ligação — e, na prática, para abortar o streaming e voltar a ligar, presumindo que tinha morrido enquanto estava escondido.
Nos telemóveis e nos browsers embutidos, estes eventos disparam muito mais vezes do que os streamings morrem — a cada mudança de separador, a cada desbloqueio, e em alguns browsers embutidos a cada dois segundos, mais ou menos. Cada um abortava um streaming perfeitamente saudável. O chat voltava a ligar-se, repetia eventos, era abortado de novo, e acabava parado em «A ligar…». Depois, dizia que o turno tinha terminado enquanto o agente ainda estava a trabalhar.
A correção: avaliar o streaming pelo facto de estar a comunicar
O chat passou a registar quando o streaming de cada projeto recebeu, pela última vez, fosse o que fosse — eventos e pings de 15 segundos incluídos. Um sinal de «visível outra vez» só aborta um streaming que esteve em silêncio durante 25 segundos: mais do que o intervalo dos pings mais um salto lento de rede, por isso um streaming vivo nunca se qualifica. Os testes verificam que um ping conta como sinal de vida, e que um streaming que acabou de fazer ping não é tratado como morto.
A regra que tirámos disto: a visibilidade de uma página diz algo sobre a página, não sobre a ligação de rede. Pergunte à ligação.
Erro 2: meia resposta depois de o telemóvel acordar
Este conseguimos reproduzir sempre no simulador de iOS:
- Inicie um chat novo e envie um pedido que demore algum tempo.
- Deixe o telemóvel adormecer durante a criação.
- Volte depois de o turno ter terminado e de o buffer de repetição de dois minutos ter expirado.
O chat mostrava os primeiros blocos da resposta, marcados como concluídos — e continuava assim até fazer refresh à página.
Porquê
Um chat novo não tem uma thread — a conversa guardada — até a primeira mensagem criar uma. Isso acontece dentro da função de envio, depois de o envio já ter capturado o passo de reconciliação, que ainda achava que não havia thread. Por isso, no fim do primeiro turno de um chat novo, a reconciliação via que não havia thread e retornava em silêncio sem pedir nada.
Normalmente ninguém reparava, porque o streaming já tinha entregue o turno inteiro. Mas um telemóvel que adormeceu durante o turno e voltou depois de o buffer de repetição de 120 segundos ter expirado não conseguia obter os eventos em falta a partir do streaming — e a reconciliação que devia ter preenchido a lacuna nunca tinha corrido.
A correção
- O envio diz à reconciliação a que thread pertence o turno, para que o primeiro turno de um chat novo seja reconciliado como qualquer outro. Se tiver aberto outro chat quando a resposta chegar, o resultado é descartado em vez de ser mostrado no sítio errado.
- Uma reconciliação falhada é tentada de novo. Um telemóvel que acorda com uma ligação má pode encontrar o turno terminado e depois falhar ao obtê-lo. Isso fica agora registado, e o chat volta a pedir quando o separador é mostrado outra vez ou quando a rede regressa.
- O «Trabalhou durante» é honesto. Cada resposta mostra quanto tempo o agente trabalhou. Se o separador nunca viu a mensagem de fim de turno do servidor, antes preenchia o valor com o seu próprio relógio — que contava desde o Enviar até o telemóvel acordar, incluindo o tempo fora. Esse valor é agora marcado como estimativa, e substituído pela duração guardada assim que o histórico chega.
O que tirámos disto
- Teste no dispositivo que as pessoas realmente usam, da forma como o usam. Os dois erros viviam na distância entre «um streaming que funciona» e «um telemóvel no bolso».
- Uma recuperação que nunca corre não é uma recuperação. O passo de reconciliação existia precisamente para apanhar este caso, e saltava-o em silêncio.
- Repita também a recuperação. O momento em que um telemóvel acorda é muitas vezes aquele em que a ligação está pior.
- Não mostre um palpite como facto. Uma duração medida pelo relógio errado é pior do que nenhuma; marque-a como estimativa ou substitua-a.
O mesmo trabalho também arrumou algumas coisas que vê enquanto um turno corre: os passos de shell são identificados pelo comando que faz o trabalho em vez de cd, as capturas de ecrã no chat mantêm o topo esquerdo da página e cabem na coluna, e um projeto novo fica com o nome gerado sem precisar de refresh.
Se está a criar a sua própria app para telemóveis, os nossos guias sobre como criar uma app web adaptada a telemóveis e apps nativas vs. aplicações web progressivas cobrem o básico. Mais sobre o próprio chat está na documentação do chat.