Sofya Developers

Em que estado minha conexão está, e o que vem depois?

Em que estado minha conexão está, e o que vem depois?

Pergunta: "em que estado minha conexão está, e o que vem depois?"

Dois eixos, nunca achatados

Guest (RoomSessionStateMachine, guest.getStatus()) tem dois eixos independentes:

  • transport: offlineconnectingonline (e retrying no meio de uma reconexão). Nada aqui é terminal — offline é descanso, não morte.
  • membership: unassociatedassociating → (awaiting_approval só quando o accessMode exige) → memberended (terminal, único, com reason).

Host (HostTransportStateMachine, host.transport) só tem o eixo transport — não existe eixo membership no host, e portanto não existe ended nele por tipo, não só por recusa em runtime. O fim de vida do host é outra coisa: destruição do objeto via host.close() (ver receita-microfone.md), não um valor neste eixo.

Os 9 reason de ended (guest)

reasonO que aconteceu
leftguest.close() — saída explícita
room_closedO host encerrou a sala (room.close())
room_expiredA sala expirou no servidor
creator_replaced(nunca alcançado pelo guest — ver assimetria abaixo)
rejectedSegunda rejeição consecutiva de aprovação
idle_timeoutConexão ociosa sem associação, servidor fechou
control_lost(eixo do host — ver HostConnection#resume, não chega ao guest)
contract_mismatchFingerprint do contrato divergiu do peer (mesmo nome, formas concretas diferentes)
protocol_version_mismatchprotocolVersion do peer é diferente do seu

Assimetria: contract_mismatch e protocol_version_mismatch terminam o guest, não o host

Não existe verbo de servidor para expulsar um guest já admitido — por isso só o guest alcança esses dois reason. O host sobrevive, na mesma sala, com o mesmo QR: um guest com contrato ou versão divergente termina sozinho (ended{reason}), e o host segue aceitando outros guests normalmente. Ver versionamento-e-deploy.md para a tabela de compatibilidade completa.

Observações não-terminais (nunca silenciadas, nunca encerram nada)

invalid_join_code, payload_too_large, bad_message, service_unavailable, occupancy_limit_not_honored e qualquer código desconhecido chegam como {code, known} pelo canal de observação (room.onObservation/equivalente do guest) — nunca terminam a sessão sozinhos, nunca são engolidos em silêncio.

Quando reconectar faz sentido vs. quando é sempre adesão nova

  • Host: uma queda de transporte com sala ainda viva dispara reconexão automática e invisível (resume_creator, usando o creatorToken em memória) — o app não vê nada acontecer, a menos que a retomada falhe de verdade (control_lost, sem retry). Entre salas (host sem sala aberta), o transporte tem prazo de 30s ocioso antes de cair; startRoom() depois disso reconecta de forma transparente.
  • Guest: não existe retomada — uma queda de transporte no meio de uma sessão de guest é sempre uma nova chamada a joinRoom, sujeita a uma nova aprovação se o accessMode exigir.

Exibição de um único indicador

deriveDisplayStatus(status) reduz os dois eixos a um único valor para exibição (nunca fonte de verdade para lógica de controle — quem precisa dos dois eixos lê getStatus() direto).

Last updated on

On this page