Como estruturar os dados que são enviados do servidor para o usuário?
Use o padrão de mensagens . Bem, você já está usando um protocolo de mensagens, mas quero dizer estruturar as alterações como mensagens ... especificamente eventos. Quando o lado do servidor muda, isso resulta em eventos de negócios. No seu cenário, as visualizações do seu cliente estão interessadas nesses eventos. Os eventos devem conter todos os dados relevantes para essa alteração (nem sempre todos os dados da visualização). A página do cliente deve atualizar as partes da exibição que está mantendo com os dados do evento.
Por exemplo, se você estava atualizando um ticker de ações e a AAPL foi alterada, não desejaria reduzir todos os preços das ações ou mesmo todos os dados sobre a AAPL (nome, descrição, etc.). Você apenas enviaria AAPL, delta e novo preço. No cliente, você atualizaria apenas o preço das ações na exibição.
Devo enviar apenas eventos como "este recurso foi atualizado e você deve recarregá-lo por meio de uma chamada AJAX" ou enviar por push os dados atualizados e substituir os dados anteriores carregados pelas chamadas AJAX iniciais?
Eu também não diria. Se você estiver enviando o evento, vá em frente e envie dados relevantes com ele (não os dados do objeto inteiro). Dê um nome para o tipo de evento que é. (A nomeação e quais dados são relevantes para esse evento estão além do escopo do funcionamento mecânico do sistema. Isso tem mais a ver com a modelagem da lógica de negócios.) Seus atualizadores de exibição precisam saber como converter cada evento específico em uma alteração precisa da visualização (ou seja, atualize apenas o que mudou).
Como definir um esqueleto coerente e escalável para os dados enviados? é uma mensagem de atualização de modelo ou "houve um erro com blahblahblah"
Eu diria que essa é uma pergunta grande e aberta que deve ser dividida em várias outras perguntas e postada separadamente.
Em geral, porém, seu sistema de back-end deve criar e despachar eventos para acontecimentos importantes para o seu negócio. Eles podem vir de feeds externos ou de atividades no próprio backend.
Como não enviar dados sobre tudo de qualquer lugar do back-end?
Use o padrão de publicação / assinatura . Quando o seu SPA carrega uma nova página que está interessada em receber atualizações em tempo real, a página deve se inscrever apenas nos eventos que pode usar e chamar a lógica de atualização de exibição à medida que esses eventos chegarem. Você provavelmente precisará de lógica pub / sub em o servidor para reduzir a carga da rede. Existem bibliotecas para Websocket pub / sub, mas não tenho certeza do que elas estão no ecossistema Rails.
Como reduzir a duplicação da lógica de negócios no servidor e no cliente?
Parece que você está tendo que atualizar os dados da visualização no cliente e no servidor. Meu palpite é que você precisa dos dados da exibição do servidor para ter um instantâneo para iniciar o cliente em tempo real. Sendo que existem duas linguagens / plataformas envolvidas (Ruby e Javascript), a lógica de atualização da visualização precisará ser escrita em ambas. Além de transpilar (que tem seus próprios problemas), não vejo uma maneira de contornar isso.
Ponto técnico: a manipulação de dados (atualização de exibição) não é lógica de negócios. Se você quer dizer validação de caso de uso, isso parece inevitável, pois as validações do cliente são necessárias para uma boa experiência do usuário, mas, no final das contas, o servidor não pode confiar nele.
Aqui está como eu vejo uma coisa assim estruturada bem.
Visualizações do cliente:
- Solicita um instantâneo da visualização e o número do último evento visto da visualização
- Isso pré-preencherá a visualização para que o cliente não precise construir do zero.
- Poderia ser sobre HTTP GET para simplificar
- Estabelece uma conexão com o websocket e assina eventos específicos, iniciando no último número de evento da exibição.
- Recebe eventos por websocket e atualiza sua exibição com base no tipo / dados do evento.
Comandos do cliente:
- Solicitar alteração de dados (HTTP PUT / POST / DELETE)
- A resposta é apenas sucesso ou falha + erro
- (O (s) evento (s) gerado (s) pela mudança virá pelo websocket e acionará uma atualização de visualização.
O lado do servidor pode realmente ser dividido em vários componentes com responsabilidades limitadas. Um que apenas processa as solicitações recebidas e cria eventos. Outro poderia gerenciar assinaturas de clientes, ouvir eventos (por exemplo, em processo) e encaminhar eventos apropriados aos assinantes. Você pode ter um terço que ouça eventos e atualize as visualizações do servidor - talvez isso ocorra antes que os assinantes recebam os eventos.
O que descrevi é uma forma de CQRS + Messaging e uma estratégia típica para resolver os tipos de problemas que você está enfrentando.
Não trouxe o Event Sourcing para essa descrição, pois não tenho certeza se é algo que você deseja assumir ou se precisa necessariamente. Mas é um padrão relacionado.