Microsserviço de Captura de Transcrição em Tempo Real
Contribuidor principal em microsserviço Ruby de produção: captura ao vivo de transcrições Zoom via RTMS dual-WebSocket, sinalização IVar thread-safe, persistência assíncrona no S3.
Overview
Este é um microsserviço de produção, de-identificado. Ingressei em uma arquitetura existente e contribuí intensamente na implementação: gerenciamento de conexões WebSocket, monitoramento de keep-alive, uploads periódicos para S3, e a suite RSpec cobrindo todos os estados de conexão e os adaptadores de arquivo. O serviço conecta à API RTMS (Real-Time Media Streaming) do Zoom para capturar transcrições ao vivo de chamadas de vídeo entre provedores e pacientes. O protocolo RTMS do Zoom exige duas conexões WebSocket simultâneas: um canal de sinalização (autenticação, heartbeats de keep-alive, mensagens de controle de stream) e um canal separado de dados de transcrição cuja URL só é conhecida após o handshake de sinalização. O runner coordena essas conexões usando `Concurrent::IVar` — callbacks de eventos WebSocket disparam em threads em background, e o thread principal do job Sidekiq bloqueia no valor do IVar com timeout configurável. Uma `Concurrent::TimerTask` gerencia uploads periódicos da transcrição em andamento para o S3 para que nenhum dado seja perdido em caso de interrupção. Na reinicialização, o runner baixa qualquer conteúdo S3 existente antes de reconectar, retomando de onde a tentativa anterior parou. Eventos de estado do job (processando, concluído, falhou) são reportados de volta à aplicação web principal via HTTP após cada resultado terminal. O desafio de engenharia é robustez em um processo stateful com tempo limitado: uma consulta médica de até três horas que não pode ser reiniciada, onde perda de dados da transcrição tem consequências clínicas. A arquitetura separa os modos de falha claramente — exceções com retry são levantadas para que o Sidekiq as tente novamente; estados terminais não retentáveis (ex: URL de servidor inválida) sinalizam falha sem lançar exceção, encerrando o job graciosamente. O monitoramento de keep-alive detecta desconexões silenciosas que a biblioteca WebSocket não exporia. *Os exemplos de código nesta página são ilustrações representativas dos padrões arquiteturais utilizados — não são código-fonte proprietário real do sistema em produção.*
Technical Stack
Runtime e Jobs
- ▸Ruby
- ▸Rack
- ▸Sidekiq
- ▸Einhorn
- ▸concurrent-ruby
Rede
- ▸Zoom RTMS API
- ▸websocket-client-simple
- ▸WebSocket de Sinalização
- ▸WebSocket de Transcrição
Armazenamento e Operações
- ▸AWS S3
- ▸RSpec
- ▸CircleCI
- ▸Docker
Key Features
Gerenciamento de duas conexões WebSocket: canal de sinalização (auth + keep-alive) e canal de dados abertos em sequência
Sinalização IVar entre threads — callbacks WebSocket em threads background comunicam a URL de transcrição e resultados terminais ao thread principal do job
Concurrent::TimerTask para uploads periódicos da transcrição em andamento para o S3 durante sessões ao vivo
Retomada na reinicialização: baixa qualquer transcrição existente do S3 antes de reconectar para que jobs interrompidos continuem de onde pararam
Monitoramento de keep-alive com timeout configurável — detecta desconexões silenciosas do Zoom que a biblioteca WebSocket não exporia
Derivação determinística de chave S3 a partir de job ID + meeting UUID, garantindo boa distribuição no bucket e retries sem colisão
Taxonomia limpa de falhas: lança exceções para erros com retry (Sidekiq tenta novamente), retorna objetos Failure para estados terminais (sem lançamento, sem retry)
Reporte de eventos de estado do job à aplicação web principal após cada transição (processando, concluído, falhou)
Code Examples
Technical Challenges
Coordenar duas conexões WebSocket sequenciais onde a URL da segunda é desconhecida até o handshake da primeira ser concluído
Gerenciar estado entre threads com segurança entre o thread de eventos WebSocket e o thread do job Sidekiq usando IVar
Detectar desconexões silenciosas WebSocket durante a sessão sem depender do evento de fechamento da biblioteca subjacente
Projetar uma estratégia de retry que preserve dados de transcrição entre reinicializações do job sem duplicar conteúdo
Distinguir modos de falha com retry dos terminais em um processo stateful e de longa duração onde lançar incorretamente causa perda de dados