Payload de diagnóstico no ping de sessão
TLDR: Enriquece o endpoint de ping de presença para aceitar e persistir um payload de diagnóstico, permitindo reconstruir uma linha do tempo de qualidade de conexão por participante em uma chamada.
Contexto
Hoje o endpoint PUT /me/meetings/:id/pings recebe payload vazio e registra apenas um timestamp no array room_pings ou wait_pings do MeetingParticipant. Não há dados sobre a qualidade da conexão, o estado do dispositivo ou métricas do Twilio.
O objetivo é conseguir responder, para um atendimento com problema reportado: “o gargalo foi a internet do usuário, o nosso servidor, ou o Twilio?” — o que exige uma linha do tempo com snapshots de diagnóstico a cada heartbeat.
Origem do problema registrada em sessions_ghost_pings_and_missing_connection_data.
Objetivos
- Aceitar payload de diagnóstico opcional no ping (compatível com clientes que enviam payload vazio)
- Persistir cada ping como um registro individual com seu snapshot de diagnóstico em JSONB
- Manter os arrays
room_pings/wait_pingsexistentes (usados empresence_statuse no serializer)
Fora de escopo
- Remover ou alterar os arrays legados
room_pings/wait_pings - Guarda de janela (
can_join?) no endpoint de pings — segue no draft ping_connection_data_and_audit - Exibição no Avo — é a room_ping_network_quality_avo
Mudanças
Nova tabela meeting_participant_pings
| Coluna | Tipo | Notas |
|---|---|---|
id |
bigint PK | |
meeting_participant_id |
bigint FK NOT NULL | |
kind |
integer NOT NULL | enum: room: 0, wait: 1 |
pinged_at |
datetime NOT NULL | timestamp do servidor |
diagnostics |
jsonb NOT NULL DEFAULT {} |
payload de diagnóstico |
created_at / updated_at |
datetime |
Schema do payload
json
{
"device": {
"user_agent": "Mozilla/5.0 ...",
"browser": "Chrome 120",
"os": "macOS 14",
"device_type": "desktop"
},
"network": {
"effective_type": "4g",
"downlink": 10.0,
"rtt": 50,
"save_data": false,
"online": true
},
"app_state": {
"visibility_state": "visible"
},
"media_devices": {
"camera": { "label": "FaceTime HD Camera", "device_id": "..." },
"microphone": { "label": "Built-in Microphone", "device_id": "..." },
"audio_output": { "label": "Built-in Speakers", "device_id": "..." }
},
"twilio": {
"network_quality_level": 4,
"network_quality_stats": {
"audio": { "send": 5, "recv": 5 },
"video": { "send": 4, "recv": 4 }
},
"room_stats": {},
"reconnection_events": [],
"errors": []
}
}
Todos os campos são opcionais — payload vazio {} é válido e resulta em diagnostics: {}.
Arquivos
| Arquivo | Ação |
|---|---|
db/migrate/TIMESTAMP_create_meeting_participant_pings.rb |
criado |
app/models/meeting_participant_ping.rb |
criado |
app/models/meeting_participant.rb |
adiciona has_many :meeting_participant_pings |
app/use_cases/meeting_participants/create_ping.rb |
atualizado para criar MeetingParticipantPing |
app/controllers/api/v1/meetings/participant_pings_controller.rb |
atualizado para aceitar payload |
spec/models/meeting_participant_ping_spec.rb |
criado |
spec/requests/api/v1/meetings/participant_pings_update_spec.rb |
atualizado |
spec/factories/meeting_participant_pings.rb |
criado |
Plano de implementação
- test: validações do model
MeetingParticipantPing—spec/models/meeting_participant_ping_spec.rb - feat: migration + model com enum
kinde associação aoMeetingParticipant - test: request spec — ping com payload de diagnóstico persiste um
MeetingParticipantPing; ping sem payload também persiste (diagnostics vazio); compatibilidade com clientes antigos - feat: atualizar
CreatePingpara criar o registro comdiagnosticsvindo do contexto - feat: atualizar o controller para receber e repassar
diagnosticsao flow - refactor: extrair a criação do
MeetingParticipantPingpara use case dedicadoMeetingParticipants::CreatePingRecordse oCreatePingficar complexo
Nota: a coluna
schema_version, criada junto desta feature para versionar o formato do JSON, foi removida antes do merge — ver remove_ping_diagnostics_schema_version.
Como verificar
```bash
# Com payload vazio (compatibilidade)
curl -X PUT …/api/v1/me/meetings/:pid/pings \
-H “Authorization: Bearer
Com payload de diagnóstico
curl -X PUT …/api/v1/me/meetings/:pid/pings \
-H “Authorization: Bearer
No console do Rails
MeetingParticipantPing.last.diagnostics MeetingParticipantPing.where(meeting_participant: participant).order(:pinged_at) ```
Documentação
O comportamento resultante, incluindo a classificação de qualidade derivada de network.rtt, está em room_ping_quality.