Construindo Conflux - Meu próprio motor de colaboração em tempo real em Rust

Imagem de capa para Building Conflux - Meu próprio motor de colaboração em tempo real em Rust

mitali

Postado em 13 de novembro

Construindo Conflux - Meu próprio motor de colaboração em tempo real em Rust

Sempre usei ferramentas em tempo real sem pensar muito em como elas realmente funcionam. Google Docs, Figma, Replit multiplayer, VSCode Live Share… você digita algo, a outra pessoa vê instantaneamente, nada quebra, ninguém sobrescreve ninguém. Simplesmente… funciona.

E por alguma razão, eu continuei me perguntando o que acontece por trás das cortinas. Como a mudança de uma pessoa aparece misteriosamente em todos os lugares? Como os conflitos são tratados? O que acontece se duas pessoas alterarem a mesma coisa ao mesmo tempo?

Eu não queria a resposta “de alto nível”. Eu queria sentir o sistema. Da mesma forma que construir Veridian me ajudou a entender o Git, eu queria entender esses sistemas de sincronização em tempo real construindo um eu mesmo.

Então eu construí Conflux, um pequeno motor de colaboração em tempo real escrito em Rust. Não porque o mundo precise de outro backend, mas porque eu precisava entender como esses sistemas em tempo real sincronizam o estado entre múltiplos usuários sem explodir.

Acontece que não é alguma tecnologia misteriosa. É um conjunto de ideias simples empilhadas de forma limpa.

Por que eu quis construir isso

Sempre que via pessoas editando a mesma coisa ao mesmo tempo, meu cérebro simplesmente assumia: “Ok, alguma biblioteca misteriosa está fazendo algo complicado.” Mas então eu aprendi sobre CRDTs, e toda a ideia fez sentido.

Um CRDT (Conflict-free Replicated Data Type) é basicamente uma estrutura de dados que nunca entra em conflito. Todas as atualizações são mescláveis. Todos podem editar livremente sem bloqueios. E eventualmente, tudo converge para o mesmo estado.

Quando percebi isso, eu quis ver por mim mesmo:

  • Como um sistema de colaboração baseado em CRDT realmente parece quando você o implementa?

O “material real” por trás disso: O que é um CRDT?

Ok, vamos decompor isso. A parte “sem conflitos” é o que importa.

O jeito “normal” (O problema):

Imagine que você e eu estamos editando um arquivo de texto.

  1. Baixamos ambos o arquivo. Ele diz: "Hello".
  2. Eu mudo minha cópia para: "Hello world".
  3. Você, ao mesmo tempo, muda sua cópia para: "Hello there".
  4. Eu faço upload da minha versão. O servidor agora tem "Hello world".
  5. Você faz upload da sua versão. O servidor agora tem "Hello there".

Minha alteração sumiu. Para sempre. Você me sobrescreveu. Isso é um conflito. É isso que sistemas de controle de versão como o Git passam todo o tempo tentando gerenciar com “conflitos de merge”.

O jeito “CRDT” (A solução):

CRDTs não funcionam assim. Eles não enviam o arquivo inteiro de um lado para o outro. Eles enviam instruções.

  1. Ambos temos o estado: "Hello".
  2. Eu faço uma alteração. Meu CRDT local não diz “o novo arquivo é ‘Hello world’”. Ele gera uma instrução: (Na posição 5, adicione: " world").
  3. Você, ao mesmo tempo, faz uma alteração. Seu CRDT gera uma instrução: (Na posição 5, adicione: " there").
  4. Eu envio minha instrução para o servidor.
  5. Você envia sua instrução para o servidor.

O servidor, e eventualmente todos os clientes, recebem ambas as instruções. A “aura” do CRDT é que ele tem uma regra matemática para mesclar essas instruções de modo que todos terminem com o mesmo estado final exato.

O texto final pode ser "Hello world there" ou "Hello there world". O importante é que nenhum dado foi perdido, e todos terminamos vendo a mesma coisa sem nunca receber um erro de “CONFLITO DE MERGE”.

É isso. Um CRDT é apenas uma estrutura de dados com um algoritmo de “merge” tão bom que ele nunca entra em conflito.

O que o Conflux realmente faz

Agora que sabemos o que é um CRDT, todo o sistema faz mais sentido.

Remova os detalhes extras, e o Conflux faz três coisas simples:

  1. Ele mantém salas – como “documentos” ou “sessões”.
  2. Cada sala contém um documento CRDT – isso armazena o estado compartilhado.
  3. Os clientes enviam instruções (atualizações), o servidor as mescla e as transmite para todos os outros.

Aqui está esse mesmo loop, mas agora faz sentido:

Você digita algo → seu CRDT local gera uma instrução → você envia essa instrução (a “atualização”) para o servidor → o servidor a mescla em seu próprio CRDT → o servidor transmite essa instrução para todos os outros clientes → seus CRDTs locais a mesclam → a interface de todos é atualizada.

É isso. Esse é todo o loop. Nenhum algoritmo sofisticado, nenhuma transformação estranha, nenhuma linha do tempo ramificada.

Apenas: atualizar → mesclar → transmitir.

E como os CRDTs são projetados para mesclar de forma limpa, nada entra em conflito.

A arquitetura (versão simples)

Para facilitar o entendimento, eu a desenhei:

Arquitetura do Conflux

Cada caixa neste diagrama tem um único trabalho. Nenhuma caixa está fazendo cinco coisas ao mesmo tempo. E essa simplicidade é o que tornou todo o sistema acessível.

Como o servidor é projetado

O servidor Conflux tem quatro partes principais, e cada uma faz exatamente um trabalho.

1. Gerenciador de Salas

Essa é a parte que acompanha todas as salas ativas.

Se uma sala não existir, ele a cria. Se uma sala ficar ociosa por muito tempo, ele a limpa.

Nada sofisticado — apenas gerenciamento de ciclo de vida.

2. Sala (Loop de Ator)

Uma sala é basicamente seu próprio mini-servidor.

Ela executa um loop que apenas escuta comandos como:

  • ApplyUpdate (Essa é nossa instrução CRDT!)
  • SetAwareness
  • Chat
  • Join
  • Leave

…e aplica essas atualizações ao seu próprio YDoc.

Esse design de “ator” significa que cada sala é isolada, o que evita a bagunça usual de estado compartilhado.

3. Servidor WebSocket

Esse é o ponto de entrada.

Ele:

  • Autentica usuários usando JWT.
  • Extrai o ID da sala da URL.
  • Atualiza a conexão para um WebSocket.
  • Encaminha mensagens recebidas para a sala correta.
  • Encaminha mensagens de saída da sala de volta para o cliente.

Ele aceita dois tipos de mensagens:

  • Texto simples: Isso se torna uma mensagem de bate-papo.
  • JSON: Isso se torna uma atualização estruturada de CRDT ou de consciência.

Isso facilita a depuração, pois você pode literalmente digitar mensagens de bate-papo a partir de um terminal.

4. Autenticação JWT

Cada login cria um novo ID de sessão (sid) dentro do token.

Isso corrige o problema de “todos fazem login com o mesmo token”. Quando um cliente se conecta, o servidor sabe:

  • Qual usuário
  • Qual sessão
  • Qual sala

É simples, mas fornece um modelo de identidade limpo.

O fluxo de sincronização (explicação fácil)

Vamos supor que duas pessoas estão editando um documento compartilhado.

  1. A pessoa A edita algo. Seu CRDT local aplica a alteração instantaneamente e gera uma instrução.
  2. A envia a instrução (a atualização) para o servidor. Isso é apenas um pequeno pedaço binário.
  3. O servidor aplica a instrução ao seu próprio CRDT. Isso mantém a cópia do documento do servidor autoritária.
  4. O servidor transmite a instrução. Todos os outros clientes naquela sala recebem a mesma atualização.
  5. Cada cliente a aplica. Seu CRDT local mescla a instrução com o que já tem.
  6. Todos permanecem sincronizados. Mesmo que muitas pessoas alterem a mesma coisa ao mesmo tempo, o CRDT lida com as mesclagens suavemente.

Parece complicado, mas vê-lo funcionar faz parecer simples.

Por que consciência e bate-papo importam

Sistemas em tempo real não são apenas sobre o conteúdo do documento.

Os usuários precisam saber:

  • Quem mais está online
  • Onde está o cursor deles
  • Quem está digitando
  • Quem entrou ou saiu

Então eu adicionei “eventos de consciência”. Essas são apenas pequenas mensagens JSON que se propagam instantaneamente para mostrar quem é quem e onde estão.

O bate-papo foi simples — se o cliente enviar texto normal em vez de JSON, o servidor trata isso como uma mensagem de bate-papo e a transmite.

É um recurso pequeno, mas faz o sistema parecer vivo.

O painel

Eu também construí um pequeno endpoint de painel:

GET /dashboard

Isso retorna:

  • ID da sala
  • Número de clientes conectados
  • Número de atualizações do documento
  • Número de eventos de consciência

Não é nada sofisticado, mas é incrivelmente útil para ver o sistema funcionando.

O que aprendi ao construir isso

Assim como o Veridian fez o Git fazer sentido para mim, o Conflux fez a colaboração em tempo real fazer sentido.

Aqui estão as coisas que se destacaram:

  • A sincronização em tempo real é principalmente sobre ordenação de mensagens e transmissão.
  • CRDTs removem cerca de 90% dos problemas de “conflito”.
  • Salas no estilo de ator tornam a concorrência surpreendentemente limpa.
  • WebSockets são muito mais fáceis de trabalhar do que eu esperava.
  • Ter um sistema de identidade adequado desde cedo evita dores de cabeça mais tarde.
  • A maioria dos “sistemas complexos” é apenas uma cadeia de etapas simples.

Antes de construir o Conflux, esses sistemas pareciam caixas pretas.

Depois de construí-lo, eles parecem algo que posso entender — e até melhorar.

Considerações finais

O Conflux não é perfeito. Provavelmente está faltando recursos. Ele definitivamente não está pronto para produção. Mas ele faz exatamente o que eu o construí para fazer e me ajudou a entender como a colaboração em tempo real funciona por trás das cortinas.

Se você está curioso sobre isso, tente construir uma versão pequena você mesmo.

Você não precisa recriar o Google Docs. Mesmo um pequeno contador compartilhado baseado em CRDT ensinará muito.

Você pode conferir o Conflux aqui:

1 curtida