O Serviço de eventos do Couchbase permite que você aja prontamente em relação a mutações (ou alterações) em seus dados. Todas as ações em Eventos são realizados com a execução de um lambda, uma pequena parte da lógica comercial escrita em JavaScript.

Os casos de uso comuns incluem enriquecimento de dados, arquivamento de documentos e integração com serviços REST externos. Veja mais detalhes aqui.

No blog a seguir, descreveremos como os erros durante a execução do ouvinte de eventos podem ser tratados. Ao usar um mecanismo de repetição, garantimos que a ação prevista seja executada, mesmo que o ouvinte de eventos falhe durante a execução.

Aplicativo de amostra

Como exemplo, implementamos parte de um aplicativo de comércio eletrônico que armazena os pedidos dos clientes em uma coleção do Couchbase. Assim que o status de um pedido é alterado para pagoSe o cliente não tiver uma confirmação de pedido, queremos enviar uma confirmação de pedido para o cliente.

Para isso, integramos um ouvinte de eventos do Couchbase com um serviço de e-mail. O ouvinte de eventos do Couchbase captará todas as alterações no documento do pedido, verificará se o pedido foi pago e, em seguida, chamará o serviço de e-mail para acionar a mensagem de confirmação.

O serviço de e-mail é um microsserviço autônomo que fornece um ponto de extremidade REST. Usamos o suporte cURL incorporado diretamente no Couchbase Eventing para chamar o microsserviço a partir do ouvinte de eventos.

Fluxo conceitual: À medida que os pedidos são atualizados no Couchbase, os eventos são acionados e captados por um ouvinte de eventos. Em seguida, o ouvinte de eventos chama o serviço de e-mail externo.

 Serviço de e-mail que retorna um erro

O cenário descrito funciona muito bem se o serviço de e-mail está operacional. No entanto, o que acontece se o serviço de e-mail está retornando um erro? As solicitações do ouvinte de eventos para o serviço de e-mail falharão e, portanto, nenhuma mensagem de confirmação será enviada ao cliente. Como no momento da falha o evento de alteração de documento do Couchbase já foi processado, nenhum novo evento para o mesmo documento é acionado, a menos que haja outra alteração nele. Para garantir que a confirmação seja enviada, precisamos tratar o erro e implementar um mecanismo de nova tentativa. Ao fazer isso, podemos contornar qualquer problema temporário do serviço externo e, ao mesmo tempo, garantir que a confirmação seja enviada.

 Há diferentes maneiras de abordar isso. No meu exemplo abaixo, optei por criar uma nova coleção chamada "retry", que armazenará referências aos documentos para os quais a execução do ouvinte de eventos falhou.

 O ouvinte de eventos captará as alterações nos documentos do pedido (etapa #1) e, em seguida, chamará o serviço de e-mail (etapa #2). Se a chamada para o serviço de e-mail for bem-sucedida, o ouvinte de eventos atualizará o status da mensagem de confirmação no documento do pedido (etapa #3). No entanto, em caso de falha, um documento de nova tentativa é criado e colocado na coleção 'retry' (etapa #3*).

Manter uma referência aos documentos nos permite identificar todas as atualizações que falharam e nos permite executá-las novamente mais tarde. Isso pode ser feito por meio da intervenção manual de um operador ou por uma nova tentativa automática usando os cronômetros de eventos do Couchbase.

  1. Iniciamos o processo de repetição adicionando um documento com um ID de documento especificado à coleção de repetição. Um cronômetro recorrente é criado com um intervalo de cronômetro fornecido.
  2. Na execução do cronômetro, todos os documentos mais antigos do que um pequeno quanta de tempo no tentar novamente são atualizados. Ao adicionar um atributo como fireRetry = true para os documentos de nova tentativa, acionamos outro evento de atualização que é captado pelo ouvinte de eventos para executar o mecanismo de nova tentativa. Isso nos dá uma mutação recursiva que ilumina todos os documentos na coleção de tentativas em paralelo. A função de nova tentativa agora é executada usando todos os threads de trabalho disponíveis em paralelo.
  3. Um evento de atualização de documento é acionado para cada documento de nova tentativa individualmente.
  4. O documento de pedido correspondente é recuperado da coleção de entrada
  5. Agora o serviço de e-mail é chamado.
  6. Se a chamada para o serviço de e-mail for bem-sucedida, o ouvinte do evento atualizará o status da mensagem de confirmação no documento do pedido e removerá o documento de nova tentativa 
  7. Em caso de falha, o documento de nova tentativa é atualizado e colocado na coleção "retry".

Revisão do código

 Agora que já estabelecemos o projeto conceitual, vamos dar uma olhada no exemplo de implementação:

Pré-requisitos:

  • Couchbase 7 Enterprise Edition. Executo o Couchbase como um cluster de nó único no Docker em minha máquina local. (https://docs.couchbase.com/server/current/install/getting-started-docker.html)
  • Para fins de desenvolvimento, criamos um cluster do Couchbase de nó único que executa os seguintes serviços:
    • Índice, consulta, eventos e serviço de dados

Observe que a instalação de um único nó não é recomendada para uso em produção.

Preparação

  • Crie um bucket chamado pedidos
  • Crie duas coleções no arquivo pedidos buckets _default scope:
    • de entrada (isso conterá todos os pedidos recebidos)
    • tentar novamente (isso conterá os documentos de nova tentativa referentes às ordens que falharam)

  • Criar balde 'metadata'. Usaremos o escopo _default e a coleção _default. O bucket de metadados é usado para os metadados do Eventing.

  • Criar um índice no tentar novamente coleção. O ouvinte de repetição consultará todos os documentos contidos na coleção usando N1QL, portanto, um índice precisa estar em vigor para que a consulta seja executada.

 Documento de pedido de modelo de dados

Para fins deste aplicativo de amostra, usamos um modelo de dados leve para o documento de pedido, contendo apenas os campos relevantes. Muitos outros campos que normalmente seriam esperados em um documento de pedido são omitidos.

Documento de repetição do modelo de dados

O documento de nova tentativa contém alguns atributos básicos, como o ID do documento do pedido, um contador de tentativas e um registro de data e hora. O documento tipo  não é necessário em nosso aplicativo, mas pode ser útil para determinar o tipo de notificação por e-mail, caso o aplicativo seja ampliado para enviar também atualizações de remessa e entrega.

Serviço de e-mail MOCK 

Vamos simular o serviço de e-mail usando um script Python simples que executa um servidor da Web local. O script responderá aleatoriamente com HTTP 200 OK ou com HTTP 406 para indicar uma falha.

  1. Atualize o endereço IP para o endereço IP de seu computador local na linha 31server = ThreadedHTTPServer(('replace with your IP', 9080), Handler)
  2. Inicie o script executando: python http.py

Ouvintes de eventos

Agora, com todos os preparativos prontos, podemos adicionar os dois ouvintes de eventos:

  • evt_send_confirmation_email - fornece a integração com o serviço de e-mail
  • evt_send_confirmation_email_retry - contém a lógica de nova tentativa
  1. Os ouvintes estão disponíveis aqui: https://github.com/puhhma/cb_eventing_retry_sample
  2. Importar os ouvintes (json ) no serviço Couchbase Eventing.

Observe que, para que os ouvintes funcionem, você precisa seguir as convenções de nomenclatura usadas neste artigo. 

Revisão evt_send_confirmation_email ouvinte

Configuração do ouvinte de eventos:

  • O ouvinte de eventos está ouvindo o de entrada na coleção pedidos balde.
  • O metadados O bucket é usado para armazenar os metadados dos ouvintes
  • Os aliases de balde bkt_order_inbound e bkt_order_retry referenciam o correspondente de entrada e tentar novamente na coleção ordem balde
  • O curlEmailServiceHost especifica o alias de URL para o EmailService simulado. Certifique-se de atualizar com seu endereço IP

 

  • Consulte os comentários inline para obter detalhes
  • O Sobre a atualização é acionada quando um documento de pedido é atualizado ou criado
  • A solicitação é construída e a solicitação HTTP POST é enviada para o EmailService usando cURL.
  • O resultado é avaliado. Caso a resposta HTTP não seja bem-sucedida, um documento de nova tentativa é construído e adicionado ao arquivo tentar novamente coleção.

  • O ouvinte de eventos está ouvindo o tentar novamente na coleção pedidos balde.
  • O metadados O bucket é usado para armazenar os metadados dos ouvintes
  • Os aliases de balde bkt_order_inbound e bkt_order_retry referenciam o correspondente de entrada e tentar novamente no balde de pedidos
  • O curlEmailServiceHost especifica o alias de URL para o EmailService simulado
  • O retryTimerIntervall especifica o intervalo do cronômetro em segundos.

 

  • O cronômetro é iniciado com a adição de um documento com o ID allow_retrys para o tentar novamente coleção
  • O cronômetro é então inicializado e a função RetryTimerCallback associada ao cronômetro
  • Quando o cronômetro é executado, a função RetryTimerCallback é chamada
  • Antes de prosseguir com o mecanismo de repetição, um novo timer é criado como a primeira etapa para garantir que ele continue em execução no caso de erros posteriores
  • Uma consulta N1QL é usada para atualizar todos os tentar novamente documentos no tentar novamente adicionando uma coleção fireRetry ao documento
  • Cada alteração de documento resulta em um evento de atualização de documento e o mecanismo de nova tentativa é executado
  • O documento do pedido é resolvido a partir do de entrada e o EmailService é chamado via cURL
  • Em caso de falha, o tentar novamente é atualizado e o documento tentativa contador aumentado

Teste o aplicativo de amostra

Agora é hora de finalmente testar o aplicativo de amostra:

  1. Certifique-se de que o EmailService simulado esteja funcionando
  2. Iniciar o evt_send_confirmation_email mas mantenha o ouvinte de eventos evt_send_confirmation_email_retry O ouvinte parou por enquanto.
  3. Crie um documento de pedido de amostra (consulte o modelo de dados acima) no console do Couchbase
  4. No caso de uma resposta bem-sucedida, o confirmationEmailSent é atualizado para true no atributo ordem documento.
  5. Em caso de falha, um documento de nova tentativa é criado no tentar novamente coleta. Como o EmailService responderá aleatoriamente com um erro, repita a etapa #3 até que ocorra um erro.
  6. Agora que capturamos um erro, vamos iniciar o ouvinte do evento de nova tentativa evt_send_confirmation_email_retry
  7. Crie um documento com o ID 'allow_retrys'. Isso inicializará o mecanismo de repetição.
  8. Após um breve período, o ouvinte se tornará ativo e começará a processar os documentos no tentar novamente coleção.
  9. Observe que o atributo "attempt" (tentativa) é aumentado a cada atualização com falha no serviço de e-mail. Em caso de sucesso, o documento do pedido é atualizado e o atributo tentar novamente documento removido do tentar novamente coleção.

Como a resposta do Email Service Mock é aleatória, talvez seja necessário repetir as etapas acima para poder observar o comportamento previsto.

Conclusão

Neste artigo, descrevo um mecanismo de repetição para lidar com condições de erro ao integrar o Couchbase Eventing a um serviço REST externo. Essa ou outras soluções semelhantes podem ser usadas para garantir que as ações previstas sejam executadas mesmo que o serviço externo esteja temporariamente com mau funcionamento. 

Ao considerar um mecanismo de nova tentativa, vários fatores precisam ser levados em conta, como o volume de novas tentativas, os threads de trabalho disponíveis para o Couchbase Eventing e as solicitações que o serviço externo pode tratar.

Você pode encontrar mais informações sobre os aspectos internos do Couchbase Eventing aqui: https://docs.couchbase.com/server/current/eventing/eventing-overview.html

Muito obrigado a Jon Strabala (gerente de produto principal da Couchbase) pela visão técnica e pelo suporte a este artigo.

Autor

Postado por Marian Puhl, engenheira de soluções

Marian Puhl é engenheiro de soluções da Couchbase na região nórdica.

Deixar uma resposta