{"id":12471,"date":"2021-11-15T10:34:56","date_gmt":"2021-11-15T18:34:56","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=12471"},"modified":"2025-06-13T22:39:19","modified_gmt":"2025-06-14T05:39:19","slug":"couchbase-eventing-handling-errors-and-retries","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/couchbase-eventing-handling-errors-and-retries\/","title":{"rendered":"Manipula\u00e7\u00e3o de eventos do Couchbase: erros e novas tentativas"},"content":{"rendered":"<p><span style=\"font-weight: 400\">O <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-overview.html\"><span style=\"font-weight: 400\">Servi\u00e7o de eventos do Couchbase<\/span><\/a><span style=\"font-weight: 400\"> permite que voc\u00ea aja prontamente em rela\u00e7\u00e3o a muta\u00e7\u00f5es (ou altera\u00e7\u00f5es) em seus dados. Todas as a\u00e7\u00f5es em <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/products\/eventing\/\">Eventos<\/a> s\u00e3o realizados com a execu\u00e7\u00e3o de um lambda, uma pequena parte da l\u00f3gica comercial escrita em JavaScript.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Os casos de uso comuns incluem enriquecimento de dados, arquivamento de documentos e integra\u00e7\u00e3o com servi\u00e7os REST externos. Veja mais detalhes <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-examples.html\"><span style=\"font-weight: 400\">aqui<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><span style=\"font-weight: 400\">No blog a seguir, descreveremos como os erros durante a execu\u00e7\u00e3o do ouvinte de eventos podem ser tratados. Ao usar um mecanismo de repeti\u00e7\u00e3o, garantimos que a a\u00e7\u00e3o prevista seja executada, mesmo que o ouvinte de eventos falhe durante a execu\u00e7\u00e3o.<\/span><\/p>\n<p><b><i>Aplicativo de amostra<\/i><\/b><\/p>\n<p><span style=\"font-weight: 400\">Como exemplo, implementamos parte de um aplicativo de com\u00e9rcio eletr\u00f4nico que armazena os pedidos dos clientes em uma cole\u00e7\u00e3o do Couchbase. Assim que o status de um pedido \u00e9 alterado para <\/span><b>pago<\/b><span style=\"font-weight: 400\">Se o cliente n\u00e3o tiver uma confirma\u00e7\u00e3o de pedido, queremos enviar uma confirma\u00e7\u00e3o de pedido para o cliente.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Para isso, integramos um ouvinte de eventos do Couchbase com um <\/span><i><span style=\"font-weight: 400\">servi\u00e7o de e-mail<\/span><\/i><span style=\"font-weight: 400\">. O ouvinte de eventos do Couchbase captar\u00e1 todas as altera\u00e7\u00f5es no documento do pedido, verificar\u00e1 se o pedido foi pago e, em seguida, chamar\u00e1 o servi\u00e7o de e-mail para acionar a mensagem de confirma\u00e7\u00e3o.<\/span><\/p>\n<p><span style=\"font-weight: 400\">O servi\u00e7o de e-mail \u00e9 um microsservi\u00e7o aut\u00f4nomo que fornece um ponto de extremidade REST. Usamos o suporte cURL incorporado diretamente no Couchbase Eventing para chamar o microsservi\u00e7o a partir do ouvinte de eventos.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12458 size-large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2021\/11\/Screen-Shot-2021-11-10-at-22.37.22-1024x352.png\" alt=\"\" width=\"900\" height=\"309\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.37.22-1024x352.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.37.22-300x103.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.37.22-768x264.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.37.22-1536x529.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.37.22-2048x705.png 2048w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.37.22-20x7.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.37.22-1320x454.png 1320w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p><i><span style=\"font-weight: 400\">Fluxo conceitual: \u00c0 medida que os pedidos s\u00e3o atualizados no Couchbase, os eventos s\u00e3o acionados e captados por um ouvinte de eventos. Em seguida, o ouvinte de eventos chama o servi\u00e7o de e-mail externo.<\/span><\/i><\/p>\n<p><span style=\"font-weight: 400\">\u00a0<\/span><b>Servi\u00e7o de e-mail que retorna um erro<\/b><\/p>\n<p><span style=\"font-weight: 400\">O cen\u00e1rio descrito funciona muito bem se o <\/span><i><span style=\"font-weight: 400\">servi\u00e7o de e-mail<\/span><\/i><span style=\"font-weight: 400\"> est\u00e1 operacional. No entanto, o que acontece se o <\/span><i><span style=\"font-weight: 400\">servi\u00e7o de e-mail<\/span><\/i><span style=\"font-weight: 400\"> est\u00e1 retornando um erro? As solicita\u00e7\u00f5es do ouvinte de eventos para o servi\u00e7o de e-mail falhar\u00e3o e, portanto, nenhuma mensagem de confirma\u00e7\u00e3o ser\u00e1 enviada ao cliente. Como no momento da falha o evento de altera\u00e7\u00e3o de documento do Couchbase j\u00e1 foi processado, nenhum novo evento para o mesmo documento \u00e9 acionado, a menos que haja outra altera\u00e7\u00e3o nele. Para garantir que a confirma\u00e7\u00e3o seja enviada, precisamos tratar o erro e implementar um mecanismo de nova tentativa. Ao fazer isso, podemos contornar qualquer problema tempor\u00e1rio do servi\u00e7o externo e, ao mesmo tempo, garantir que a confirma\u00e7\u00e3o seja enviada.<\/span><\/p>\n<p><span style=\"font-weight: 400\">\u00a0<\/span><span style=\"font-weight: 400\">H\u00e1 diferentes maneiras de abordar isso. No meu exemplo abaixo, optei por criar uma nova cole\u00e7\u00e3o chamada \"retry\", que armazenar\u00e1 refer\u00eancias aos documentos para os quais a execu\u00e7\u00e3o do ouvinte de eventos falhou.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12459 size-large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2021\/11\/Screen-Shot-2021-11-10-at-22.39.25-1024x435.png\" alt=\"\" width=\"900\" height=\"382\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.39.25-1024x435.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.39.25-300x127.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.39.25-768x326.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.39.25-1536x652.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.39.25-2048x869.png 2048w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.39.25-20x8.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.39.25-1320x560.png 1320w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<p><span style=\"font-weight: 400\">\u00a0<\/span><span style=\"font-weight: 400\">O ouvinte de eventos captar\u00e1 as altera\u00e7\u00f5es nos documentos do pedido (etapa #1) e, em seguida, chamar\u00e1 o servi\u00e7o de e-mail (etapa #2). Se a chamada para o servi\u00e7o de e-mail for bem-sucedida, o ouvinte de eventos atualizar\u00e1 o status da mensagem de confirma\u00e7\u00e3o no documento do pedido (etapa #3). No entanto, em caso de falha, um documento de nova tentativa \u00e9 criado e colocado na cole\u00e7\u00e3o 'retry' (etapa #3*).<\/span><\/p>\n<p><span style=\"font-weight: 400\">Manter uma refer\u00eancia aos documentos nos permite identificar todas as atualiza\u00e7\u00f5es que falharam e nos permite execut\u00e1-las novamente mais tarde. Isso pode ser feito por meio da interven\u00e7\u00e3o manual de um operador ou por uma nova tentativa autom\u00e1tica usando os cron\u00f4metros de eventos do Couchbase.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12460 size-large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2021\/11\/Screen-Shot-2021-11-10-at-22.40.24-1024x435.png\" alt=\"\" width=\"900\" height=\"382\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.40.24-1024x435.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.40.24-300x127.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.40.24-768x326.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.40.24-1536x652.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.40.24-2048x869.png 2048w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.40.24-20x8.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-10-at-22.40.24-1320x560.png 1320w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Iniciamos o processo de repeti\u00e7\u00e3o adicionando um documento com um ID de documento especificado \u00e0 cole\u00e7\u00e3o de repeti\u00e7\u00e3o. Um cron\u00f4metro recorrente \u00e9 criado com um intervalo de cron\u00f4metro fornecido.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Na execu\u00e7\u00e3o do cron\u00f4metro, todos os documentos mais antigos do que um pequeno quanta de tempo no <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> s\u00e3o atualizados. Ao adicionar um atributo como <\/span><i><span style=\"font-weight: 400\">fireRetry = true<\/span><\/i><span style=\"font-weight: 400\"> para os documentos de nova tentativa, acionamos outro evento de atualiza\u00e7\u00e3o que \u00e9 captado pelo ouvinte de eventos para executar o mecanismo de nova tentativa. Isso nos d\u00e1 uma muta\u00e7\u00e3o recursiva que ilumina todos os documentos na cole\u00e7\u00e3o de tentativas em paralelo. A fun\u00e7\u00e3o de nova tentativa agora \u00e9 executada usando todos os threads de trabalho dispon\u00edveis em paralelo.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Um evento de atualiza\u00e7\u00e3o de documento \u00e9 acionado para cada documento de nova tentativa individualmente.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O documento de pedido correspondente \u00e9 recuperado da cole\u00e7\u00e3o de entrada<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Agora o servi\u00e7o de e-mail \u00e9 chamado.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Se a chamada para o servi\u00e7o de e-mail for bem-sucedida, o ouvinte do evento atualizar\u00e1 o status da mensagem de confirma\u00e7\u00e3o no documento do pedido e remover\u00e1 o documento de nova tentativa\u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Em caso de falha, o documento de nova tentativa \u00e9 atualizado e colocado na cole\u00e7\u00e3o \"retry\".<\/span><\/li>\n<\/ol>\n<p><b>Revis\u00e3o do c\u00f3digo<\/b><\/p>\n<p><span style=\"font-weight: 400\">\u00a0<\/span><span style=\"font-weight: 400\">Agora que j\u00e1 estabelecemos o projeto conceitual, vamos dar uma olhada no exemplo de implementa\u00e7\u00e3o:<\/span><\/p>\n<p><b>Pr\u00e9-requisitos<\/b><span style=\"font-weight: 400\">:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Couchbase 7 Enterprise Edition. Executo o Couchbase como um cluster de n\u00f3 \u00fanico no Docker em minha m\u00e1quina local. (https:\/\/docs.couchbase.com\/server\/current\/install\/getting-started-docker.html)<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Para fins de desenvolvimento, criamos um cluster do Couchbase de n\u00f3 \u00fanico que executa os seguintes servi\u00e7os:<\/span>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">\u00cdndice, consulta, eventos e servi\u00e7o de dados<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400\">Observe que a instala\u00e7\u00e3o de um \u00fanico n\u00f3 n\u00e3o \u00e9 recomendada para uso em produ\u00e7\u00e3o.<\/span><\/p>\n<p><b>Prepara\u00e7\u00e3o<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Crie um bucket chamado <\/span><b><i>pedidos<\/i><\/b><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Crie duas cole\u00e7\u00f5es no arquivo <\/span><b><i>pedidos<\/i><\/b><span style=\"font-weight: 400\"> buckets _default scope:<\/span>\n<ul>\n<li style=\"font-weight: 400\"><b>de entrada<\/b><span style=\"font-weight: 400\"> (isso conter\u00e1 todos os pedidos recebidos)<\/span><\/li>\n<li style=\"font-weight: 400\"><b>tentar novamente<\/b><span style=\"font-weight: 400\"> (isso conter\u00e1 os documentos de nova tentativa referentes \u00e0s ordens que falharam)<\/span><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12461 size-large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2021\/11\/eventing1-1024x331.png\" alt=\"\" width=\"900\" height=\"291\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing1-1024x331.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing1-300x97.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing1-768x248.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing1-1536x496.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing1-20x6.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing1-1320x427.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing1.png 1600w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Criar balde <\/span><b>'metadata'<\/b><span style=\"font-weight: 400\">. Usaremos o escopo _default e a cole\u00e7\u00e3o _default. O bucket de metadados \u00e9 usado para os metadados do Eventing.<\/span><\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12462 size-large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2021\/11\/eventing2-1024x226.png\" alt=\"\" width=\"900\" height=\"199\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing2-1024x226.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing2-300x66.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing2-768x169.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing2-1536x339.png 1536w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing2-20x4.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing2-1320x291.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/eventing2.png 1600w\" sizes=\"auto, (max-width: 900px) 100vw, 900px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Criar um \u00edndice no <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> cole\u00e7\u00e3o. O ouvinte de repeti\u00e7\u00e3o consultar\u00e1 todos os documentos contidos na cole\u00e7\u00e3o usando N1QL, portanto, um \u00edndice precisa estar em vigor para que a consulta seja executada.<\/span><\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">CREATE PRIMARY INDEX idx_default_primary ON orders._default.retry USING GSI;<\/pre>\n<p><span style=\"font-weight: 400\">\u00a0<\/span><b><i>Documento de pedido de modelo de dados<\/i><\/b><\/p>\n<p><span style=\"font-weight: 400\">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\u00e3o omitidos.<\/span><\/p>\n<pre class=\"lang:default decode:true\">{\r\n\u00a0\u00a0\"email\": \"customer_email\",\r\n\u00a0\u00a0\"paymentStatus\": \"initiated\",\r\n\u00a0\u00a0\"confirmationEmailSent\": false,\r\n\u00a0\u00a0\"items\": [\r\n\u00a0\u00a0\u00a0\u00a0{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"name\": \"Swedish Meatballs 500g\",\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"amount\": 2,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"unitPrice\": 9.95\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0]\r\n}<\/pre>\n<p><b><i>Documento de repeti\u00e7\u00e3o do modelo de dados<\/i><\/b><\/p>\n<p><span style=\"font-weight: 400\">O documento de nova tentativa cont\u00e9m alguns atributos b\u00e1sicos, como o ID do documento do pedido, um contador de tentativas e um registro de data e hora. O documento <\/span><i><span style=\"font-weight: 400\">tipo <\/span><\/i><span style=\"font-weight: 400\">\u00a0n\u00e3o \u00e9 necess\u00e1rio em nosso aplicativo, mas pode ser \u00fatil para determinar o tipo de notifica\u00e7\u00e3o por e-mail, caso o aplicativo seja ampliado para enviar tamb\u00e9m atualiza\u00e7\u00f5es de remessa e entrega.<\/span><\/p>\n<pre class=\"lang:default decode:true\">{\r\n\u00a0\u00a0\"type\": \"confirmation\",\r\n\u00a0\u00a0\"docId\": \"order_140\",\r\n\u00a0\u00a0\"attempt\": 1,\r\n\u00a0\u00a0\"ts\": 1632775908319\r\n}<\/pre>\n<p><b><i>Servi\u00e7o de e-mail MOCK\u00a0<\/i><\/b><\/p>\n<p><span style=\"font-weight: 400\">Vamos simular o servi\u00e7o de e-mail usando um script Python simples que executa um servidor da Web local. O script responder\u00e1 aleatoriamente com HTTP 200 OK ou com HTTP 406 para indicar uma falha.<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Atualize o endere\u00e7o IP para o endere\u00e7o IP de seu computador local na linha 31<\/span><em>server = ThreadedHTTPServer(('replace with your IP', 9080), Handler)<\/em><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Inicie o script executando: python http.py<\/span><\/li>\n<\/ol>\n<p><b>Ouvintes de eventos<\/b><\/p>\n<p><span style=\"font-weight: 400\">Agora, com todos os preparativos prontos, podemos adicionar os dois ouvintes de eventos:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400\"><b>evt_send_confirmation_email<\/b><span style=\"font-weight: 400\"> - fornece a integra\u00e7\u00e3o com o servi\u00e7o de e-mail<\/span><\/li>\n<li style=\"font-weight: 400\"><b>evt_send_confirmation_email_retry<\/b><span style=\"font-weight: 400\"> - cont\u00e9m a l\u00f3gica de nova tentativa<\/span><\/li>\n<\/ul>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Os ouvintes est\u00e3o dispon\u00edveis aqui: https:\/\/github.com\/puhhma\/cb_eventing_retry_sample<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Importar os ouvintes (<\/span><i><span style=\"font-weight: 400\">json<\/span><\/i><span style=\"font-weight: 400\"> ) no servi\u00e7o Couchbase Eventing.<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400\">Observe que, para que os ouvintes funcionem, voc\u00ea precisa seguir as conven\u00e7\u00f5es de nomenclatura usadas neste artigo.\u00a0<\/span><\/p>\n<p><b>Revis\u00e3o <\/b><b><i>evt_send_confirmation_email<\/i><\/b><b> ouvinte<\/b><\/p>\n<p><span style=\"font-weight: 400\">Configura\u00e7\u00e3o do ouvinte de eventos:<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12465 size-large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2021\/11\/function-1-602x1024.png\" alt=\"\" width=\"602\" height=\"1024\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-1-602x1024.png 602w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-1-176x300.png 176w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-1-768x1307.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-1-902x1536.png 902w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-1-300x511.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-1-12x20.png 12w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-1.png 940w\" sizes=\"auto, (max-width: 602px) 100vw, 602px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O ouvinte de eventos est\u00e1 ouvindo o <\/span><i><span style=\"font-weight: 400\">de entrada<\/span><\/i><span style=\"font-weight: 400\"> na cole\u00e7\u00e3o <\/span><i><span style=\"font-weight: 400\">pedidos<\/span><\/i><span style=\"font-weight: 400\"> balde.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O <\/span><i><span style=\"font-weight: 400\">metadados<\/span><\/i><span style=\"font-weight: 400\"> O bucket \u00e9 usado para armazenar os metadados dos ouvintes<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Os aliases de balde <\/span><i><span style=\"font-weight: 400\">bkt_order_inbound<\/span><\/i><span style=\"font-weight: 400\"> e <\/span><i><span style=\"font-weight: 400\">bkt_order_retry<\/span><\/i><span style=\"font-weight: 400\"> referenciam o correspondente <\/span><i><span style=\"font-weight: 400\">de entrada<\/span><\/i><span style=\"font-weight: 400\"> e <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> na cole\u00e7\u00e3o <\/span><i><span style=\"font-weight: 400\">ordem<\/span><\/i><span style=\"font-weight: 400\"> balde<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O <\/span><i><span style=\"font-weight: 400\">curlEmailServiceHost<\/span><\/i><span style=\"font-weight: 400\"> especifica o alias de URL para o EmailService simulado. Certifique-se de atualizar com seu endere\u00e7o IP<\/span><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<pre class=\"lang:default decode:true\">\/\/ OnUpdate is invoked for all documents created\/updated in the 'inbound' bucket\r\nfunction OnUpdate(doc, meta) {\r\n\u00a0\u00a0\u00a0\u00a0\/\/ determine if document status is 'paid' &amp; confirmation email was not previously sent\r\n\u00a0\u00a0\u00a0\u00a0if( doc.paymentStatus === \"paid\" &amp;&amp; !doc.confirmationEmailSent ) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SendConfirmationMail(doc, meta.id);\r\n\u00a0\u00a0\u00a0\u00a0} else {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (debug_level &gt; 1)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log(\"Nothing to do for: \" + meta.id);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n}\r\n\r\nfunction SendConfirmationMail(doc, docId) {\r\n\u00a0\u00a0try {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ build the request to the EmailService\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var request = {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0path: 'sendConfirmation',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0body: doc\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0 perform the cURL request using the URL alias 'curlEmailServiceHost' from the settings\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var response = curl('POST', curlEmailServiceHost, request);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (response.status != 200) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ this did not work as expected\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (debug_level &gt; 1) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log(\"docId\", docId, \"cURL POST failed response.status:\",response.status);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ create retry document referencing the documentId and store in 'retry' bucket\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bkt_order_retry[docId] = {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"docId\": docId,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"attempt\": 1,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"ts\": Date.now()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} else {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (debug_level &gt; 5) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log(\"cURL POST success, sent\",docId,\"response.body:\",response.body);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ update confirmationEmailSent status\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0doc.confirmationEmailSent = true;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bkt_order_inbound[docId] = doc;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0} catch (e) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log(\"ERROR cURL request had an exception:\",e)\r\n\u00a0\u00a0}\r\n}<\/pre>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Consulte os coment\u00e1rios inline para obter detalhes<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O <\/span><i><span style=\"font-weight: 400\">Sobre a atualiza\u00e7\u00e3o <\/span><\/i><span style=\"font-weight: 400\">\u00e9 acionada quando um documento de pedido \u00e9 atualizado ou criado<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">A solicita\u00e7\u00e3o \u00e9 constru\u00edda e a solicita\u00e7\u00e3o HTTP POST \u00e9 enviada para o EmailService usando cURL.<\/span><\/li>\n<li style=\"font-weight: 400\">O resultado \u00e9 avaliado. Caso a resposta HTTP n\u00e3o seja bem-sucedida, um documento de nova tentativa \u00e9 constru\u00eddo e adicionado ao arquivo <i>tentar novamente<\/i> cole\u00e7\u00e3o.<\/li>\n<\/ul>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12464 size-large\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2021\/11\/function-564x1024.png\" alt=\"\" width=\"564\" height=\"1024\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-564x1024.png 564w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-165x300.png 165w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-768x1393.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-847x1536.png 847w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-300x544.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function-11x20.png 11w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/function.png 882w\" sizes=\"auto, (max-width: 564px) 100vw, 564px\" \/><\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O ouvinte de eventos est\u00e1 ouvindo o <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> na cole\u00e7\u00e3o <\/span><i><span style=\"font-weight: 400\">pedidos<\/span><\/i><span style=\"font-weight: 400\"> balde.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O <\/span><i><span style=\"font-weight: 400\">metadados<\/span><\/i><span style=\"font-weight: 400\"> O bucket \u00e9 usado para armazenar os metadados dos ouvintes<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Os aliases de balde <\/span><i><span style=\"font-weight: 400\">bkt_order_inbound<\/span><\/i><span style=\"font-weight: 400\"> e <\/span><i><span style=\"font-weight: 400\">bkt_order_retry<\/span><\/i><span style=\"font-weight: 400\"> referenciam o correspondente <\/span><i><span style=\"font-weight: 400\">de entrada<\/span><\/i><span style=\"font-weight: 400\"> e <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> no balde de pedidos<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O <\/span><i><span style=\"font-weight: 400\">curlEmailServiceHost<\/span><\/i><span style=\"font-weight: 400\"> especifica o alias de URL para o EmailService simulado<\/span><\/li>\n<li style=\"font-weight: 400\">O <i>retryTimerIntervall<\/i> especifica o intervalo do cron\u00f4metro em segundos.<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">function OnUpdate(doc, meta) {\r\n\u00a0\u00a0\u00a0\u00a0if (meta.id === \"allow_retrys\") {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ the timer is initialized by creating document with id = 'allow_retrys'\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CreateRetryTimer({\"id\": meta.id, \"mode\": \"initial\"});\r\n\u00a0\u00a0\u00a0\u00a0} else if (doc.fireRetry) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ process retry documents\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0SendConfirmationMail(doc, meta.id);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n}\r\n\r\nfunction CreateRetryTimer(context) {\r\n\u00a0\u00a0\u00a0\u00a0if (debug_level &gt; 2) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log('From CreateRetryTimer: creating timer', context.mode, context.id);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\/\/ Create a timestamp 'retryTimerInterval' seconds (from the settings) from now\r\n\u00a0\u00a0\u00a0\u00a0var timerStartTime = new Date();\r\n\u00a0\u00a0\u00a0\u00a0\/\/ Get current time &amp; add 'retryTimerInterval' sec. to it.\r\n\u00a0\u00a0\u00a0\u00a0timerStartTime.setSeconds(timerStartTime.getSeconds() + retryTimerInterval);\r\n\u00a0\u00a0\u00a0\u00a0\/\/ Create a document to use as out for our context\r\n\u00a0\u00a0\u00a0\u00a0createTimer(RetryTimerCallback, timerStartTime, context.id, context);\r\n}\r\n\r\nfunction RetryTimerCallback(context) {\r\n\u00a0\u00a0\u00a0\u00a0if (debug_level &gt; 2) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log('From RetryTimerCallback: timer fired', context);\r\n\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\/\/ rearm the timer ASAP, to ensure timer keeps running in the event\r\n\u00a0\u00a0\u00a0\u00a0\/\/ of later\u00a0 errors or script timeouts in later \"recurring work\".\r\n\u00a0\u00a0\u00a0\u00a0CreateRetryTimer({ \"id\": context.id, \"mode\": \"via_callback\" });\r\n\u00a0\u00a0\u00a0\u00a0\/\/ Update all retry documents in the 'retry' bucket. Exclude the 'allow_retys' document\r\n\u00a0\u00a0\u00a0\u00a0\/\/ and any documents that were created more than 15 seconds ago, in order to avoid retry 'to early'.\r\n\u00a0\u00a0\u00a0\u00a0N1QL(\"UPDATE orders._default.retry SET fireRetry = true WHERE meta().id != 'allow_retrys' AND ts &lt; DATE_ADD_MILLIS(NOW_MILLIS(), -15, 'second')\");\r\n}\r\n\r\nfunction SendConfirmationMail(retryDoc, docId) {\r\n\u00a0\u00a0try {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ resolve order document by id\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var doc = bkt_order_inbound[docId];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ build the request\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var request = {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0path: 'sendConfirmation',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0body: doc\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0};\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/\u00a0 perform the cURL request using the URL alias from the settings\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0var response = curl('POST', curlEmailServiceHost, request);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (response.status != 200) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ this did not work as expected\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (debug_level &gt; 1) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log(\"docId\", docId, \"cURL POST failed response.status:\",response.status);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ increment attempt count in retry document\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0retryDoc.attempt = ++retryDoc.attempt;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ Set fireRetry = false, to avoid retry execution with this document change\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0retryDoc.fireRetry = false;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0retryDoc.ts = Date.now();\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ update retry document\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bkt_order_retry[docId] = retryDoc;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0} else {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if (debug_level &gt; 5) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log(\"cURL POST success, sent\",docId,\"response.body:\",response.body);\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0doc.confirmationEmailSent = true;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0bkt_order_inbound[docId] = doc;\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/ delete the retry document\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0delete bkt_order_retry[docId];\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\u00a0 } catch (e) {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0log(\"ERROR cURL request had an exception:\",e)\r\n\u00a0\u00a0}\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<ul>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O cron\u00f4metro \u00e9 iniciado com a adi\u00e7\u00e3o de um documento com o ID <\/span><b>allow_retrys<\/b><span style=\"font-weight: 400\"> para o <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> cole\u00e7\u00e3o<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O cron\u00f4metro \u00e9 ent\u00e3o inicializado e a fun\u00e7\u00e3o RetryTimerCallback associada ao cron\u00f4metro<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Quando o cron\u00f4metro \u00e9 executado, a fun\u00e7\u00e3o RetryTimerCallback \u00e9 chamada<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Antes de prosseguir com o mecanismo de repeti\u00e7\u00e3o, um novo timer \u00e9 criado como a primeira etapa para garantir que ele continue em execu\u00e7\u00e3o no caso de erros posteriores<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Uma consulta N1QL \u00e9 usada para atualizar todos os <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> documentos no <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> adicionando uma cole\u00e7\u00e3o <\/span><i><span style=\"font-weight: 400\">fireRetry<\/span><\/i><span style=\"font-weight: 400\"> ao documento<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Cada altera\u00e7\u00e3o de documento resulta em um evento de atualiza\u00e7\u00e3o de documento e o mecanismo de nova tentativa \u00e9 executado<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O documento do pedido \u00e9 resolvido a partir do <\/span><i><span style=\"font-weight: 400\">de entrada<\/span><\/i><span style=\"font-weight: 400\"> e o EmailService \u00e9 chamado via cURL<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Em caso de falha, o <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> \u00e9 atualizado e o documento <\/span><i><span style=\"font-weight: 400\">tentativa<\/span><\/i><span style=\"font-weight: 400\"> contador aumentado<\/span><\/li>\n<\/ul>\n<p><b>Teste o aplicativo de amostra<\/b><\/p>\n<p><span style=\"font-weight: 400\">Agora \u00e9 hora de finalmente testar o aplicativo de amostra:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Certifique-se de que o EmailService simulado esteja funcionando<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Iniciar o <\/span><b><i>evt_send_confirmation_email <\/i><\/b><span style=\"font-weight: 400\">mas mantenha o ouvinte de eventos <\/span><b><i>evt_send_confirmation_email_retry <\/i><\/b><span style=\"font-weight: 400\">O ouvinte parou por enquanto.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Crie um documento de pedido de amostra (consulte o modelo de dados acima) no console do Couchbase<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">No caso de uma resposta bem-sucedida, o <\/span><span style=\"font-weight: 400\">confirmationEmailSent <\/span><span style=\"font-weight: 400\">\u00e9 atualizado para true no atributo <\/span><i><span style=\"font-weight: 400\">ordem<\/span><\/i><span style=\"font-weight: 400\"> documento.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Em caso de falha, um documento de nova tentativa \u00e9 criado no <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> coleta. Como o EmailService responder\u00e1 aleatoriamente com um erro, repita a etapa #3 at\u00e9 que ocorra um erro.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Agora que capturamos um erro, vamos iniciar o ouvinte do evento de nova tentativa <\/span><b><i>evt_send_confirmation_email_retry<\/i><\/b><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Crie um documento com o ID 'allow_retrys'. Isso inicializar\u00e1 o mecanismo de repeti\u00e7\u00e3o.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Ap\u00f3s um breve per\u00edodo, o ouvinte se tornar\u00e1 ativo e come\u00e7ar\u00e1 a processar os documentos no <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> cole\u00e7\u00e3o.<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Observe que o atributo \"attempt\" (tentativa) \u00e9 aumentado a cada atualiza\u00e7\u00e3o com falha no servi\u00e7o de e-mail. Em caso de sucesso, o documento do pedido \u00e9 atualizado e o atributo <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> documento removido do <\/span><i><span style=\"font-weight: 400\">tentar novamente<\/span><\/i><span style=\"font-weight: 400\"> cole\u00e7\u00e3o.<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400\">Como a resposta do Email Service Mock \u00e9 aleat\u00f3ria, talvez seja necess\u00e1rio repetir as etapas acima para poder observar o comportamento previsto.<\/span><\/p>\n<p><b>Conclus\u00e3o<\/b><\/p>\n<p><span style=\"font-weight: 400\">Neste artigo, descrevo um mecanismo de repeti\u00e7\u00e3o para lidar com condi\u00e7\u00f5es de erro ao integrar o Couchbase Eventing a um servi\u00e7o REST externo. Essa ou outras solu\u00e7\u00f5es semelhantes podem ser usadas para garantir que as a\u00e7\u00f5es previstas sejam executadas mesmo que o servi\u00e7o externo esteja temporariamente com mau funcionamento.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Ao considerar um mecanismo de nova tentativa, v\u00e1rios fatores precisam ser levados em conta, como o volume de novas tentativas, os threads de trabalho dispon\u00edveis para o Couchbase Eventing e as solicita\u00e7\u00f5es que o servi\u00e7o externo pode tratar.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Voc\u00ea pode encontrar mais informa\u00e7\u00f5es sobre os aspectos internos do Couchbase Eventing aqui: <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-overview.html\"><span style=\"font-weight: 400\">https:\/\/docs.couchbase.com\/server\/current\/eventing\/eventing-overview.html<\/span><\/a><\/p>\n<p><span style=\"font-weight: 400\">Muito obrigado a Jon Strabala (gerente de produto principal da Couchbase) pela vis\u00e3o t\u00e9cnica e pelo suporte a este artigo.<\/span><\/p>","protected":false},"excerpt":{"rendered":"<p>The Couchbase Eventing Service allows you to promptly act on mutations (or changes) to your data. All actions in Eventing are accomplished by executing a lambda, a small piece of business logic written in JavaScript. Common use cases include data [&hellip;]<\/p>","protected":false},"author":77950,"featured_media":12473,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[2273],"tags":[],"ppma_author":[9323],"class_list":["post-12471","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-eventing"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Couchbase Eventing Handling Errors and Retries w\/ Examples<\/title>\n<meta name=\"description\" content=\"This post will outline how errors during the event listener execution can be handled. By using a retry mechanism ensure the anticipated action is performed.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/pt\/couchbase-eventing-handling-errors-and-retries\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Couchbase Eventing Handling Errors and Retries\" \/>\n<meta property=\"og:description\" content=\"This post will outline how errors during the event listener execution can be handled. By using a retry mechanism ensure the anticipated action is performed.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/couchbase-eventing-handling-errors-and-retries\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-11-15T18:34:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T05:39:19+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash-1024x683.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"683\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Marian Puhl, Solutions Engineer\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Marian Puhl, Solutions Engineer\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/\"},\"author\":{\"name\":\"Marian Puhl, Solutions Engineer\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/b2fc479528e2819b50082a425cf381e3\"},\"headline\":\"Couchbase Eventing Handling Errors and Retries\",\"datePublished\":\"2021-11-15T18:34:56+00:00\",\"dateModified\":\"2025-06-14T05:39:19+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/\"},\"wordCount\":1751,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash.jpg\",\"articleSection\":[\"Eventing\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/\",\"name\":\"Couchbase Eventing Handling Errors and Retries w\/ Examples\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash.jpg\",\"datePublished\":\"2021-11-15T18:34:56+00:00\",\"dateModified\":\"2025-06-14T05:39:19+00:00\",\"description\":\"This post will outline how errors during the event listener execution can be handled. By using a retry mechanism ensure the anticipated action is performed.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash.jpg\",\"width\":7952,\"height\":5304,\"caption\":\"Creating JavaScript UDFs to traverse hierarchy in Couchbase SQL++\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Couchbase Eventing Handling Errors and Retries\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/b2fc479528e2819b50082a425cf381e3\",\"name\":\"Marian Puhl, Solutions Engineer\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/1f65549252c18bb3651eaa3a78e46169\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/07\/marian-puhl-couchbase-engineering.jpeg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/07\/marian-puhl-couchbase-engineering.jpeg\",\"caption\":\"Marian Puhl, Solutions Engineer\"},\"description\":\"Marian Puhl is a Solutions Engineer at Couchbase in the Nordic region.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/marian-puhl\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Couchbase Eventing Handling Errors and Retries w\/ Examples","description":"This post will outline how errors during the event listener execution can be handled. By using a retry mechanism ensure the anticipated action is performed.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/pt\/couchbase-eventing-handling-errors-and-retries\/","og_locale":"pt_BR","og_type":"article","og_title":"Couchbase Eventing Handling Errors and Retries","og_description":"This post will outline how errors during the event listener execution can be handled. By using a retry mechanism ensure the anticipated action is performed.","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/couchbase-eventing-handling-errors-and-retries\/","og_site_name":"The Couchbase Blog","article_published_time":"2021-11-15T18:34:56+00:00","article_modified_time":"2025-06-14T05:39:19+00:00","og_image":[{"width":1024,"height":683,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash-1024x683.jpg","type":"image\/jpeg"}],"author":"Marian Puhl, Solutions Engineer","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Marian Puhl, Solutions Engineer","Est. reading time":"9 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/"},"author":{"name":"Marian Puhl, Solutions Engineer","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/b2fc479528e2819b50082a425cf381e3"},"headline":"Couchbase Eventing Handling Errors and Retries","datePublished":"2021-11-15T18:34:56+00:00","dateModified":"2025-06-14T05:39:19+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/"},"wordCount":1751,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash.jpg","articleSection":["Eventing"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/","url":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/","name":"Couchbase Eventing Handling Errors and Retries w\/ Examples","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash.jpg","datePublished":"2021-11-15T18:34:56+00:00","dateModified":"2025-06-14T05:39:19+00:00","description":"This post will outline how errors during the event listener execution can be handled. By using a retry mechanism ensure the anticipated action is performed.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/thisisengineering-raeng-64YrPKiguAE-unsplash.jpg","width":7952,"height":5304,"caption":"Creating JavaScript UDFs to traverse hierarchy in Couchbase SQL++"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/couchbase-eventing-handling-errors-and-retries\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Couchbase Eventing Handling Errors and Retries"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/b2fc479528e2819b50082a425cf381e3","name":"Marian Puhl, engenheira de solu\u00e7\u00f5es","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/1f65549252c18bb3651eaa3a78e46169","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/07\/marian-puhl-couchbase-engineering.jpeg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/07\/marian-puhl-couchbase-engineering.jpeg","caption":"Marian Puhl, Solutions Engineer"},"description":"Marian Puhl \u00e9 engenheiro de solu\u00e7\u00f5es da Couchbase na regi\u00e3o n\u00f3rdica.","url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/marian-puhl\/"}]}},"authors":[{"term_id":9323,"user_id":77950,"is_guest":0,"slug":"marian-puhl","display_name":"Marian Puhl, Solutions Engineer","avatar_url":{"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/07\/marian-puhl-couchbase-engineering.jpeg","url2x":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/07\/marian-puhl-couchbase-engineering.jpeg"},"author_category":"","last_name":"Puhl","first_name":"Marian","job_title":"","user_url":"","description":"Marian Puhl \u00e9 engenheiro de solu\u00e7\u00f5es da Couchbase na regi\u00e3o n\u00f3rdica."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/12471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/77950"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=12471"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/12471\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/12473"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=12471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=12471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=12471"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=12471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}