Não faz muito tempo, escrevi sobre a criação de um aplicativo de bate-papo que usava o Angular 2 para o front-end e o Golang para o back-end. A comunicação de mensagens entre os dois foi possível graças aos websockets. Neste exemplo, qualquer número de clientes Angular 2 poderia se conectar ao aplicativo Golang e se comunicar uns com os outros, mas os novos clientes não poderiam ver as mensagens anteriores. Isso ocorre porque os dados não estavam sendo salvos depois de serem enviados.

Vamos expandir o aplicativo Golang que foi criado anteriormente e incluir Couchbase para que as mensagens sejam salvas depois de enviadas e, em seguida, sejam carregadas quando novos clientes se conectarem.
Os requisitos
Há alguns requisitos para dar andamento a esse projeto. Eles são os seguintes:
- Couchbase Server 4.1+.
- Golang 1.7+.
- Um cliente e um servidor de bate-papo em funcionamento, como visto no tutorial anterior.
É muito importante que você tenha o servidor de bate-papo funcionando, pois muito do que veremos será uma revisão do que foi feito no guia anterior. A inclusão de um banco de dados NoSQL do Couchbase será trivial, mas o Couchbase com suporte a consultas N1QL já deve estar instalado.
Criação de um bucket do Couchbase Server e adição de um índice
Este projeto exigirá a criação de pelo menos um bucket no Couchbase. Esse bucket armazenará todos os dados de mensagens enviadas de e para o servidor de bate-papo Golang. Os dados armazenados serão mais ou menos assim:
1 2 3 4 5 |
{ "remetente": "62f142ce-7308-4dae-9eb0-3ae61d363c22", "content" (conteúdo): "Olá, Nic Raboy!", "timestamp" (registro de data e hora): 1482174735 } |
Você pode optar por usar o Couchbase padrão ou você pode optar por criar um novo. Usarei um bucket chamado exemplo neste projeto.
Como a consulta estará envolvida, precisamos definir pelo menos um índice que possa ser usado em nosso bucket. Esse índice pode ser criado usando o Couchbase Query Workbench ou o Couchbase Shell (CBQ). Usando uma dessas ferramentas, execute o seguinte:
1 |
CRIAR PRIMÁRIO ÍNDICE ON `exemplo` USO GSI; |
Com o índice criado, o aplicativo pode ser modificado para incluir o armazenamento NoSQL.
Estabelecimento de uma conexão com o servidor Couchbase
Antes de começarmos a salvar os dados no Couchbase, é necessário estabelecer uma conexão a partir do nosso aplicativo Go. Se você seguiu a instrução guia anteriorseu aplicativo Go pode estar em um caminho semelhante a $GOPATH/src/github.com/nraboy/realtime-chat/main.go.
Antes de abrir seu arquivo de código-fonte, você precisa instalar o Golang SDK for Couchbase. Ele pode ser instalado executando:
1 |
ir obter github.com/couchbase/gocb |
Com o SDK do Couchbase instalado, abra $GOPATH/src/github.com/nraboy/realtime-chat/main.go e inclua a seguinte linha fora de qualquer função:
1 |
var balde *gocb.Balde |
Incluímos a variável fora de qualquer função porque queremos que ela seja global em nosso aplicativo, não local em uma função específica.
Dentro do principal
antes da goroutina do nosso gerenciador de clientes, queremos estabelecer uma conexão com o cluster e abrir um determinado bucket. Isso pode ser feito da seguinte forma:
1 2 |
agrupamento, _ := gocb.Conectar("couchbase://localhost") balde, _ = agrupamento.OpenBucket("exemplo", "") |
No cenário acima, eu me conectei ao meu nó em execução local e abri o arquivo exemplo que foi criado anteriormente.
Neste ponto, o Couchbase está pronto para ser usado e podemos nos concentrar em nosso modelo de dados.
Definição do modelo de dados JSON do Couchbase
Vimos o modelo de dados JSON proposto anteriormente, mas precisamos torná-lo possível por meio do Golang. Isso é feito por meio do uso de uma estrutura de dados Golang.
Perto das outras estruturas de dados existentes, inclua o seguinte:
1 2 3 4 5 6 |
tipo Mensagem estrutura { Remetente string `json:"sender,omitempty"` Beneficiário string `json:"recipient,omitempty"` Conteúdo string `json:"content,omitempty"` Carimbo de data/hora int64 `json:"timestamp,omitempty"` } |
O acima Mensagem
tem propriedades mapeadas para elementos JSON. Um elemento que não estamos optando por usar, mas que faria sentido ter é o Beneficiário
. Nunca se sabe se, no futuro, você desejará enviar mensagens para clientes específicos.
O Couchbase pode trabalhar diretamente com o Mensagem
para salvar e ler dados. Para enviá-los por um websocket, eles podem ser transformados em JSON.
Salvando e carregando mensagens com o Couchbase
Isso nos leva a fazer o salvamento e o carregamento de dados. Temos a configuração do banco de dados com uma conexão estabelecida. Temos nosso modelo de dados. Agora vamos colocá-lo em uso.
Para simplificar, manteremos o ID de cada documento exclusivo. Isso pode ser feito por meio de uma biblioteca UUID que pode ser instalada por meio da linha de comando da seguinte forma:
1 |
ir obter github.com/satori/ir.uuid |
No aplicativo, adicione um saveMessage
como o seguinte:
1 2 3 |
func saveMessage(mensagem *Mensagem) { balde.Upsert(uuid.NovoV4().Cordas(), mensagem, 0) } |
Observe que estamos aceitando um Mensagem
gerando uma nova chave de documento e inserindo-a no banco de dados. Isso significa que cada mensagem será armazenada como seu próprio documento.
Então, que tal carregar dados quando uma conexão é estabelecida?
1 2 3 4 5 6 7 8 |
func (gerente *Gerenciador de clientes) loadMessages(cliente *Cliente) { consulta := gocb.NewN1qlQuery("SELECT `example`.* FROM `example` ORDER BY timestamp") linhas, _ := balde.ExecutarN1qlQuery(consulta, nulo) var fila Mensagem var jsonMessage []byte para linhas.Próximo(&fila) { jsonMessage, _ = json.Marechal(fila) cliente.enviar |
No exemplo acima loadMessages
aceitamos um método Cliente
que representará o cliente recém-conectado. O cliente que deseja obter o histórico de mensagens.
Uma consulta N1QL é criada para buscar todas as mensagens e ordená-las pelo carimbo de data/hora
valor. Cada resultado da consulta é transformado em JSON e adicionado ao canal do cliente para ser enviado.
Então, como usamos esses dois métodos?
Quando uma conexão de websocket é estabelecida, o gerenciador de clientes registra o cliente para transmissão. Isso acontece na seção iniciar
método. No iniciar
há uma instrução switch para o registro do cliente. Vamos modificá-la para que se pareça com o seguinte:
1 2 3 4 |
caso con := < -gerente.registro: gerente.clientes[con] = verdadeiro jsonMessage, _ := json.Marechal(&Mensagem{Conteúdo: "/Um novo soquete foi conectado."}) gerente.enviar(jsonMessage, con) gerente.loadMessages(con) |
Observe que, depois que a conexão do cliente é registrada, pegamos a conexão e a passamos para o loadMessages
que acabamos de criar. Isso enviará todas as mensagens armazenadas anteriormente para esse cliente específico.
O salvamento das mensagens será um pouco diferente.
No tutorial anterior, criamos um arquivo ler
método. Modifique-o para que fique parecido com o seguinte:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
func (c *Cliente) ler() { adiar func(){ gerente.cancelar o registro < -c c.soquete.Fechar() }() para{ _, mensagem, erro := c.soquete.ReadMessage() se erro != nulo { gerente.cancelar o registro < -c c.soquete.Fechar() quebra } mensagem := &Mensagem { Remetente: c.id, Conteúdo: string(mensagem), Carimbo de data/hora:(tempo.Agora()).Unix(), } jsonMessage, _ := json.Marechal(mensagem) saveMessage(mensagem) gerente.transmissão < -jsonMessage } } |
O que é importante são as linhas a seguir:
1 2 3 4 5 6 |
mensagem := &Mensagem { Remetente: c.id, Conteúdo: string(mensagem), Carimbo de data/hora: (tempo.Agora()).Unix(), } saveMessage(mensagem) |
O servidor receberá uma mensagem do cliente e criará uma mensagem real de Mensagem
com informações adicionais, como quem a enviou e quando. Essa mensagem é então salva no banco de dados.
Tente executar o aplicativo Golang novamente com o cliente Angular 2. Ele deve salvar as mensagens agora.
Conclusão
Acabamos de ver como adicionar o Couchbase a um Exemplo anterior de websocket que eu escrevi. No exemplo anterior, tínhamos um aplicativo de bate-papo cliente e servidor que se comunicava usando websockets. Expandimos esse exemplo e começamos a salvar os dados da mensagem no Couchbase para que pudessem ser carregados por novos participantes do bate-papo.
Bom trabalho
Obrigado!