{"id":1655,"date":"2014-12-16T19:35:27","date_gmt":"2014-12-16T19:35:27","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=1655"},"modified":"2017-05-03T13:26:40","modified_gmt":"2017-05-03T20:26:40","slug":"introducing-libcouchbase-24-0","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/introducing-libcouchbase-24-0\/","title":{"rendered":"Apresentando a libcouchbase 2.4"},"content":{"rendered":"<p><em>libcouchbase<\/em><span style=\"font-family: inherit; font-size: 1em;\">\u00a02.4.0 est\u00e1 aqui. Ele oferece grandes aprimoramentos arquitet\u00f4nicos e v\u00e1rios novos recursos, melhorando as vers\u00f5es anteriores.<\/span><\/p>\n<p><em>Este blog foi originalmente escrito para a vers\u00e3o 2.4.0 DP1, mas foi modificado para refletir as diferen\u00e7as entre a visualiza\u00e7\u00e3o do desenvolvedor e a vers\u00e3o atual do GA (2.4.0)<\/em><\/p>\n<p><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\"><strong>Links diretos para download<\/strong>:\u00a0<\/span><a style=\"font-family: inherit; font-size: 1em; line-height: 23px;\" href=\"https:\/\/packages.couchbase.com\/clients\/c\/index.html\">https:\/\/packages.couchbase.com\/clients\/c\/index.html<\/a><\/p>\n<p><strong>Documenta\u00e7\u00e3o da API:\u00a0<\/strong><a href=\"https:\/\/docs.couchbase.com\/sdk-api\/couchbase-c-client-2.4.0\/\">https:\/\/docs.couchbase.com\/sdk-api\/couchbase-c-client-2.4.0\/<\/a><\/p>\n<p><span style=\"color: #007da4; font-size: 23px; font-weight: 600; line-height: 1.4;\">Melhorias internas<\/span><\/p>\n<h3><span style=\"color: #be2228; font-size: 23px;\">Estruturas de pacotes<\/span><\/h3>\n<p>Codinome\u00a0<em>pacote-ng<\/em>Na verdade, essa vers\u00e3o da libcouchbase come\u00e7ou como uma tentativa de refatorar o tratamento de pacotes de modo que eles fossem considerados objetos de primeira classe. O pacote de solicita\u00e7\u00e3o \u00e9 a moeda principal da biblioteca, pois vincula o cookie solicitado pelo usu\u00e1rio \u00e0 resposta do servidor.<\/p>\n<p>Na vers\u00e3o 2.4, os pacotes de solicita\u00e7\u00e3o s\u00e3o encapsulados no\u00a0<em>mc_PACKET<\/em>\u00a0que cont\u00e9m informa\u00e7\u00f5es sobre o cookie, os buffers do pr\u00f3prio pacote e o estado do pacote (ou seja, recebido, liberado, tentado novamente, com erro, pendente). A estrutura do pacote vem junto com a estrutura\u00a0<em>mcreq<\/em>\u00a0que fornece uma API unificada para alocar, liberar, analisar e reprogramar pacotes para servidores individuais.<\/p>\n<h3>Filas e buffers de pacotes<\/h3>\n<p>Os pacotes agora s\u00e3o inseridos em uma fila (ou em um\u00a0<em>mc_PIPELINE<\/em>) que cont\u00e9m a ordena\u00e7\u00e3o dos pacotes como uma lista vinculada. Os pacotes s\u00e3o adicionados \u00e0 fila na ordem em que s\u00e3o agendados.<\/p>\n<p>Como a efici\u00eancia de E\/S \u00e9 melhor com buffers cont\u00edguos, o\u00a0<em>mc_PACKET<\/em>\u00a0n\u00e3o cont\u00e9m o buffer em seu pr\u00f3prio objeto, mas sim um ponteiro especial para uma regi\u00e3o em um buffer cont\u00edguo gerenciado por um alocador cont\u00edguo especial em ordem. Isso permite que os pacotes vivam como objetos \"independentes\" e, ao mesmo tempo, que seus dados de rede reais sejam compactados em sequ\u00eancia. Assim como os pr\u00f3prios buffers de rede, cada objeto de pacote tamb\u00e9m \u00e9 alocado usando uma inst\u00e2ncia separada desse alocador.<\/p>\n<p>O alocador reside no\u00a0<em>netbuf<\/em>\u00a0que tamb\u00e9m cont\u00e9m estruturas e rotinas para lidar com fragmentos de buffer de forma eficiente e prepar\u00e1-los adequadamente para serem enviados \u00e0 rede, enquanto lida com condi\u00e7\u00f5es como envios parciais.<\/p>\n<h3>Aprimoramentos de E\/S<\/h3>\n<p>O sistema de E\/S foi refatorado e modularizado dentro do\u00a0<em>lcbio<\/em>\u00a0m\u00f3dulo (<em>src\/lcbio<\/em>). A adi\u00e7\u00e3o not\u00e1vel \u00e9 a do\u00a0<em>lcbio_CTX<\/em>\u00a0que cont\u00e9m rotinas eficientes e unificadas para leituras, grava\u00e7\u00f5es e tratamento de erros de soquetes, abstraindo o modelo de E\/S subjacente (por exemplo, baseado em conclus\u00e3o, como IOCP ou libuv, ou baseado em eventos, como select ou libevent) de sua API.<\/p>\n<h3>Robustez durante altera\u00e7\u00f5es de configura\u00e7\u00e3o e falhas<\/h3>\n<p>As altera\u00e7\u00f5es de configura\u00e7\u00e3o e as falhas agora s\u00e3o tratadas com eleg\u00e2ncia. Quando uma nova configura\u00e7\u00e3o \u00e9 recebida e o objeto de servidor relacionado (<em>mc_SERVER)<\/em>\u00a0precisa mudar de posi\u00e7\u00e3o, sua conex\u00e3o TCP \u00e9 mantida intacta e \u00e9 percorrida por todos os comandos (pacotes) que n\u00e3o s\u00e3o mais mapeados para ela. Para cada um desses comandos, a estrutura mc_PACKET \u00e9 duplicada e colocada na fila adequada, enquanto o buffer de envio possivelmente subjacente ainda \u00e9 enviado para a rede e sua resposta \u00e9 ignorada. Isso nos permite manter o fluxo TCP intacto e simplesmente engolir a resposta de erro relacionada (e prevista) proveniente do servidor.<\/p>\n<p>Se uma conex\u00e3o TCP for interrompida repentinamente e nenhuma nova configura\u00e7\u00e3o for recebida, os pacotes relacionados poder\u00e3o ser colocados em uma fila de repeti\u00e7\u00e3o\u00a0<em>ou<\/em>\u00a0falharam imediatamente. Os comandos que s\u00e3o repetidos e os que falham podem ser configurados pelo usu\u00e1rio.<\/p>\n<p>O comportamento durante a opera\u00e7\u00e3o em um cluster degradado tamb\u00e9m foi aprimorado. Agora, as opera\u00e7\u00f5es que s\u00e3o roteadas para n\u00f3s ausentes s\u00e3o colocadas na fila e a biblioteca emitir\u00e1 de forma transparente uma solicita\u00e7\u00e3o de configura\u00e7\u00e3o para o cluster, permitindo que o aplicativo tente novamente o item sem executar etapas adicionais.<\/p>\n<h3>Mais testes<\/h3>\n<p>Como essa vers\u00e3o da biblioteca foi refatorada para modularizar o maior n\u00famero poss\u00edvel de sistemas, isso significa que o teste de cada um dos m\u00f3dulos se torna mais simples, pois eles t\u00eam um comportamento mais bem definido e menos depend\u00eancias. Foram adicionados muitos testes novos dedicados ao gerenciamento de buffer, ao tratamento de pacotes e ao tratamento de E\/S bruta. Todos esses testes n\u00e3o fazem uso da fun\u00e7\u00e3o <em>CouchbaseMock<\/em> servidor ou quaisquer recursos externos, mas s\u00e3o totalmente contidos e determin\u00edsticos.<\/p>\n<h2>Nova documenta\u00e7\u00e3o da API<\/h2>\n<p>A documenta\u00e7\u00e3o da API agora \u00e9 gerada via <em>Doxygen<\/em>. O Doxygen \u00e9 um gerador de documenta\u00e7\u00e3o de c\u00f3digo aberto para v\u00e1rias plataformas que gera documenta\u00e7\u00e3o de API com base nos coment\u00e1rios do c\u00f3digo-fonte. Isso permitir\u00e1 que a documenta\u00e7\u00e3o da nossa API seja mais atualizada, de modo que, desde que uma nova API seja adicionada e contenha coment\u00e1rios, ela aparecer\u00e1 na documenta\u00e7\u00e3o da API e, se uma API mais antiga for removida, ela desaparecer\u00e1 da documenta\u00e7\u00e3o.<\/p>\n<p>Al\u00e9m disso, adicionamos formalmente\u00a0<em>atributos da interface\u00a0<\/em>para todas as nossas APIs para ajud\u00e1-lo a determinar a estabilidade e o roteiro de uma determinada chamada de API. Isso nos permite identificar claramente se uma interface espec\u00edfica \u00e9 experimental (ou\u00a0<em>vol\u00e1til<\/em>), ou se pode ser usado no c\u00f3digo de produ\u00e7\u00e3o com a certeza de que n\u00e3o ser\u00e1 modificado ou removido em vers\u00f5es posteriores.<\/p>\n<h2>Novos recursos<\/h2>\n<h3>Suporte a SSL para o Couchbase Enterprise 3.0<\/h3>\n<p>A vers\u00e3o 2.4 cont\u00e9m suporte (via <em>OpenSSL<\/em>) para se comunicar com o servidor usando o protocolo SSL. O suporte a SSL \u00e9 implementado inteiramente em uma das camadas dentro de\u00a0<em>lcbio<\/em>\u00a0e, portanto, reside\u00a0<em>embaixo<\/em>\u00a0<em>lcbio_CTX<\/em>. Dessa forma, o suporte a SSL \u00e9 praticamente transparente para a maioria dos sistemas da biblioteca. Por padr\u00e3o, a biblioteca ainda se conectar\u00e1 em um modo n\u00e3o criptografado (no entanto, sua senha SASL ainda ser\u00e1 criptografada, se poss\u00edvel)<\/p>\n<h3>Suporte \u00e0 cadeia de conex\u00e3o<\/h3>\n<p>Tamb\u00e9m \u00e9 novidade o suporte a uma nova maneira de especificar como se conectar ao cluster. \u00c0 medida que mais e mais op\u00e7\u00f5es de conex\u00e3o s\u00e3o adicionadas \u00e0 biblioteca, foi necess\u00e1rio fornecer um formato uniforme para que os usu\u00e1rios declarassem como e o que desejam usar ao se conectar ao cluster. <a href=\"https:\/\/docs.google.com\/document\/d\/172ausWsYt3eYYOZ1lYHVS8ccbrrVJaGwHIRsf_O_Hyc\/edit?disco=AAAAAHZn6S4#\">Brett Lawson prop\u00f4s um novo URI-like<\/a>\u00a0que permite especificar as op\u00e7\u00f5es de conex\u00e3o em um formato claro, conciso e n\u00e3o amb\u00edguo. O uso de um formato URI permite coisas como a possibilidade de especificar essas configura\u00e7\u00f5es em um arquivo de configura\u00e7\u00e3o (para que voc\u00ea n\u00e3o precise analisar manualmente v\u00e1rias configura\u00e7\u00f5es e depois combin\u00e1-las com os campos de estrutura apropriados).<\/p>\n<p>Como a libcouchbase \u00e9 usada principalmente como uma camada central de bibliotecas de n\u00edvel superior (como Python, Node.JS e Ruby), a exposi\u00e7\u00e3o de uma op\u00e7\u00e3o de conex\u00e3o de string facilita que todas essas linguagens compartilhem uma interface comum e uma base de c\u00f3digo comum ao especificar como se conectar ao cluster.<\/p>\n<p>Como demonstra\u00e7\u00e3o, uma string de conex\u00e3o como\u00a0<em><span style=\"font-family: courier new,courier,monospace;\">couchbase:\/\/foo.com,bar.com,baz.com\/mybucket?operation_timeout=5000000&amp;detailed_errcodes=true<\/span>\u00a0<\/em>\u00a0usar\u00e1\u00a0<em>foo.com<\/em>,\u00a0<em>bar.com<\/em>e\u00a0<em>baz.com<\/em>\u00a0como n\u00f3s para se conectar ao bucket\u00a0<em>meu cesto<\/em>, aplicando um tempo limite de opera\u00e7\u00e3o de 5 segundos e ativando c\u00f3digos de erro detalhados (outro novo recurso da biblioteca).<\/p>\n<h3>Nova API de opera\u00e7\u00e3o comum<\/h3>\n<p>Um novo conjunto de APIs de solicita\u00e7\u00e3o (vol\u00e1teis) foi adicionado nesta vers\u00e3o para formar a base das APIs da pr\u00f3xima vers\u00e3o principal da biblioteca. Essas APIs operam em um \u00fanico comando por vez e seguem um padr\u00e3o de entrada\/sa\u00edda, em que um usu\u00e1rio \"entra\" em um contexto de agendamento, agenda v\u00e1rios comandos e depois \"sai\". Em contraste com as APIs 2.x, em que cada comando agendava implicitamente uma descarga para a rede, essas novas APIs s\u00f3 agendam uma descarga quando \"saem\" do contexto atual. Isso permite a constru\u00e7\u00e3o eficiente de v\u00e1rias opera\u00e7\u00f5es em lote sem a necessidade de alocar uma matriz de estruturas de comando para isso; por exemplo.<\/p>\n<p>Al\u00e9m disso, as novas APIs de solicita\u00e7\u00e3o e resposta permitem a reutiliza\u00e7\u00e3o de c\u00f3digo em opera\u00e7\u00f5es comuns, criando uma ABI comum para as estruturas de solicita\u00e7\u00e3o e resposta. Nessa nova API, todas as estruturas de solicita\u00e7\u00e3o s\u00e3o compat\u00edveis com o layout da\u00a0<em>lcb_CMDBASE\u00a0<\/em>\u00a0e todas as estruturas de resposta s\u00e3o compat\u00edveis com o layout do\u00a0<em>lcb_RESPBASE<\/em>\u00a0estrutura. Da mesma forma, o novo mecanismo de retorno de chamada permite que um \u00fanico retorno de chamada manipule mais de um tipo de opera\u00e7\u00e3o, em que o retorno de chamada recebe uma constante inteira indicando o tipo de opera\u00e7\u00e3o e um\u00a0<em>lcb_RESPBASE<\/em>\u00a0que pode ser convertida para a estrutura de resposta espec\u00edfica da opera\u00e7\u00e3o apropriada, se necess\u00e1rio.<\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace;\">#include<br \/>\n#inclui<br \/>\n#inclui<br \/>\n#includestatic void<br \/>\nop_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *resp)<br \/>\n{<br \/>\nfprintf(stderr, \"Obteve o resultado para a chave %.*s com o c\u00f3digo 0x%xn\",<br \/>\n(int)resp-&gt;nkey, resp-&gt;key, resp-&gt;rc);<br \/>\nse (resp-&gt;rc != LCB_SUCCESS) {<br \/>\nretorno;<br \/>\n}<\/p>\n<p>Se (cbtype == LCB_CALLBACK_GET) {<br \/>\nconst lcb_RESPGET *gresp = (const lcb_RESPGET *)resp;<br \/>\nfprintf(stderr, \"RETRIEVED ITEMn\");<br \/>\nfprintf(stderr, \"VALUE: %.*snFLAGS: 0x%xnCAS=0x%lxn\",<br \/>\n(int)gresp-&gt;nvalue, gresp-&gt;value, gresp-&gt;itmflags, gresp-&gt;cas);<br \/>\n} else if (cbtype == LCB_CALLBACK_STORE) {<br \/>\nfprintf(stderr, \"STORED ITEMn\");<br \/>\nfprintf(stderr, \"CAS: 0x%lxn\", resp-&gt;cas);<br \/>\n}<br \/>\n}<\/p>\n<p>int main(void)<br \/>\n{<br \/>\ninst\u00e2ncia lcb_t;<br \/>\nn\u00e3o assinado ii;<br \/>\nstruct lcb_create_st cropts = { 0 };<br \/>\nlcb_error_t err;<\/p>\n<p>cropts.v.v3.connstr = \"couchbase:\/\/10.0.0.99\/default\";<br \/>\nlcb_create(&amp;instance, &amp;cropts);<br \/>\nlcb_connect(instance);<br \/>\nlcb_wait(instance);<br \/>\nlcb_install_callback3(instance, LCB_CALLBACK_GET, op_callback);<br \/>\nlcb_install_callback3(instance, LCB_CALLBACK_STORE, op_callback);<\/p>\n<p>for (ii = 0; ii &lt; 10; ii++) {<\/p>\n<p>lcb_CMDSTORE store_cmd = { 0 };<br \/>\nlcb_CMDGET get_cmd = { 0 };<br \/>\nchar buf[1024];<br \/>\nsize_t nbuf;<\/p>\n<p>sprintf(buf, \"Key_%d\", ii);<br \/>\nnbuf = strlen(buf);<\/p>\n<p>LCB_CMD_SET_KEY(&amp;store_cmd, buf, nbuf);<br \/>\nLCB_CMD_SET_VALUE(&amp;store_cmd, \"Value\", strlen(\"Value\"));<br \/>\nstore_cmd.operation = LCB_SET;<br \/>\nerr = lcb_store3(instance, NULL, &amp;store_cmd);<br \/>\nSe (err != LCB_SUCCESS){<br \/>\npausa;<br \/>\n}<br \/>\nLCB_CMD_SET_KEY(&amp;get_cmd, buf, nbuf);<br \/>\nerr = lcb_get3(instance, NULL, &amp;get_cmd);<br \/>\nse (err != LCB_SUCCESS) {<br \/>\npausa;<br \/>\n}<br \/>\n}<br \/>\nSe (err == LCB_SUCCESS) {<br \/>\nlcb_sched_leave(instance);<br \/>\nlcb_wait(instance);<br \/>\n} else {<br \/>\nlcb_sched_fail(instance);<br \/>\n}<br \/>\nlcb_destroy(instance);<br \/>\nretornar 0;<br \/>\n}<\/p>\n<\/div>\n<\/div>\n<h3>Manuseio eficiente da carga \u00fatil<\/h3>\n<p>V\u00e1rios recursos foram introduzidos no cliente 2.4 para permitir o manuseio mais eficiente da carga \u00fatil entre o aplicativo e a biblioteca. Por padr\u00e3o, a biblioteca copiar\u00e1 o valor de um\u00a0<em>definir<\/em>\u00a0de modo a n\u00e3o exigir que o buffer de valor passado permane\u00e7a na mem\u00f3ria v\u00e1lida durante toda a opera\u00e7\u00e3o. Da mesma forma para\u00a0<em>obter<\/em>\u00a0o aplicativo deve copiar o buffer de valores se quiser que os dados persistam fora do retorno de chamada.<\/p>\n<p>Foi adicionado um suporte experimental que permite que voc\u00ea indique a biblioteca\u00a0<em>n\u00e3o<\/em>\u00a0para copiar o buffer de valores (para\u00a0<em>definir<\/em>) por meio das opera\u00e7\u00f5es\u00a0<em><a href=\"https:\/\/docs.couchbase.com\/sdk-api\/couchbase-c-client-2.4.0\/kvbuf_8h.html#structlcb___v_a_l_b_u_f\">lcb_VALBUF<\/a> estrutura\u00a0<\/em>(fornecido como um campo dentro do\u00a0<em>lcb_CMDSTORE<\/em>) estrutura:.<\/p>\n<p>Da mesma forma, existe um campo adicional no\u00a0<em>lcb_RESPGET<\/em>\u00a0estrutura chamada <em>bufh<\/em>. Esse campo cont\u00e9m um ponteiro opaco para um\u00a0<em>al\u00e7a do buffer<\/em>. Esse identificador de buffer pode ser <a href=\"https:\/\/docs.couchbase.com\/sdk-api\/couchbase-c-client-2.4.0\/group___l_c_b___p_k_t_f_w_d.html#ga05147342799a9423d2eb71786e192af4\">definido para persistir\u00a0<em>externo\u00a0<\/em>do retorno de chamada<\/a>permitindo que os dados da resposta permane\u00e7am v\u00e1lidos at\u00e9 que o pr\u00f3prio identificador do buffer seja\u00a0<em>liberado<\/em>. Internamente, isso usa uma contagem de refer\u00eancia<\/p>\n<h3>Despacho de pacotes brutos<\/h3>\n<p><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">Agora voc\u00ea pode fornecer pacotes memcached brutos \u00e0 libcouchbase para enviar a um servidor e receber um pacote memcached bruto como resposta. Isso permite acesso de n\u00edvel inferior \u00e0 funcionalidade do pacote e permite que voc\u00ea crie um servidor proxy. O recurso \u00e9 implementado de forma que os buffers de resposta n\u00e3o sejam copiados para a chamada de retorno e possam ser mantidos ativos fora da chamada de retorno, de modo que n\u00e3o seja necess\u00e1rio copiar as respostas GET em um buffer tempor\u00e1rio para processamento. Da mesma forma, o pr\u00f3prio pacote de solicita\u00e7\u00e3o tamb\u00e9m pode, opcionalmente, n\u00e3o ser copiado, mas ter uma chamada de retorno invocada quando n\u00e3o for mais necess\u00e1rio para a biblioteca.<\/span><\/p>\n<p><span style=\"color: #be2228; font-size: 23px; font-weight: 600; line-height: 1.4;\">Novas APIs de configura\u00e7\u00e3o de cluster<\/span><\/p>\n<p><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">Uma nova chamada de retorno foi adicionada \u00e0 biblioteca, notificando o usu\u00e1rio se o bootstrap inicial foi bem-sucedido ou falhou. Isso era feito anteriormente usando a fun\u00e7\u00e3o\u00a0<\/span><em style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">retorno de chamada de erro (lcb_set_error_callback()<\/em><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">) e o\u00a0<\/span><em style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">retorno de chamada de configura\u00e7\u00e3o\u00a0<\/em><em style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">(lcb_set_configuration_callback)<\/em><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">A chamada de retorno de erro seria invocada em um erro inicial e a chamada de retorno de configura\u00e7\u00e3o seria invocada quando o cluster recebesse uma nova configura\u00e7\u00e3o. No entanto, a chamada de retorno de erro tamb\u00e9m seria chamada toda vez que um n\u00f3 espec\u00edfico falhasse, fazendo com que os clientes falhassem prematuramente se v\u00e1rios n\u00f3s fossem passados e apenas o primeiro da lista falhasse. O novo\u00a0<\/span><em style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">retorno de chamada do bootstrap<\/em><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">\u00a0\u00e9 chamado apenas uma vez e somente durante a cria\u00e7\u00e3o inicial com um c\u00f3digo de erro definido que indica o sucesso ou a falha do bootstrap. Para clientes n\u00e3o ass\u00edncronos, voc\u00ea pode simplesmente usar\u00a0<\/span><em style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">lcb_get_bootstrap_status()<\/em><span style=\"font-family: inherit; font-size: 1em; line-height: 1.4375em;\">\u00a0e n\u00e3o precisar depender de um retorno de chamada:<\/span><\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace;\">inst\u00e2ncia lcb_t;<br \/>\nstruct lcb_create_st cropt = {<br \/>\n.vers\u00e3o = 3,<br \/>\n.v.3.dsn = \"couchbase:\/\/cbnode1,cbnode2\/mybucket\"<br \/>\n};<br \/>\nlcb_error_t err = lcb_create(&amp;instance, &amp;cropt);<br \/>\nse (err != LCB_SUCCESS) {<br \/>\n\/\/ tratar o erro;<br \/>\n}<br \/>\n#if I_AM_BLOCKING<br \/>\nerr = lcb_connect(instance);<br \/>\nlcb_wait(instance);<br \/>\nSe ((err = lcb_get_bootstrap_status(instance)) != LCB_SUCCESS)<br \/>\n{<br \/>\nprintf(\"Failed to bootstrap: %sn\", lcb_strerror(instance, err));<br \/>\n}<br \/>\n\/\/ fazer comandos<br \/>\n#else \/* SOU ASYNC *\/<br \/>\nstatic void bootstrap_callback(lcb_t instance, lcb_error_t err) {<br \/>\nse (err != LCB_SUCCESS) {<br \/>\nprintf(\"N\u00e3o foi poss\u00edvel fazer o bootstrap\");<br \/>\n} else {<br \/>\nlcb_GETCMD gcmd = { 0 };<br \/>\nLCB_KREQ_SIMPLE(&amp;req.key, \"foo\", 3);<br \/>\nlcb_sched_enter(instance);<br \/>\nlcb_get3(instance, NULL, &amp;gcmd);<br \/>\nlcb_sched_leave(instance);<br \/>\n}<br \/>\n}<br \/>\nlcb_set_bootstrap_callback(instance, bootstrap_callback);<br \/>\nlcb_connect(instance); \/\/ Retornar ao loop de eventos ou chamar lcb_wait()<br \/>\n#endif<\/div>\n<\/div>\n<p><span style=\"font-family: inherit; font-size: 1em;\">Al\u00e9m disso, um <\/span><em>lcb_refresh_config()<\/em><span style=\"font-family: inherit; font-size: 1em;\">\u00a0foi adicionada para for\u00e7ar o cliente a solicitar uma nova configura\u00e7\u00e3o do cluster. Isso \u00e9 \u00fatil para \"for\u00e7ar\" uma reconfigura\u00e7\u00e3o nos casos em que muitos tempos limite est\u00e3o sendo encontrados ou para impor uma pol\u00edtica de atualiza\u00e7\u00e3o personalizada no aplicativo.<\/span><\/p>\n<p><span style=\"font-family: inherit; font-size: 1em;\">Por fim, o <\/span><em>vbucket<\/em><span style=\"font-family: inherit; font-size: 1em;\">\u00a0A API foi exposta, permitindo a inspe\u00e7\u00e3o da configura\u00e7\u00e3o atual que est\u00e1 sendo usada pela biblioteca. A nova API est\u00e1 localizada em\u00a0<\/span><em>libcouchbase\/vbucket.h<\/em><span style=\"font-family: inherit; font-size: 1em;\">\u00a0(dentro do diret\u00f3rio de cabe\u00e7alhos).\u00a0<\/span><\/p>\n<div class=\"geshifilter\">\n<div class=\"text geshifilter-text\" style=\"font-family: monospace;\">#include<br \/>\nlcbvb_CONFIG *config;<br \/>\nlcb_error_t err;<br \/>\nerr = lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_VBCONFIG, &amp;config);<br \/>\n\/\/ Verificar erro<br \/>\nprintf(\"A revis\u00e3o da configura\u00e7\u00e3o atual \u00e9 %dn\", lcbvb_get_revision(config));<br \/>\nprintf(\"Cluster has %u serversn\", lcbvb_get_nservers(config));<\/div>\n<\/div>\n<p><span style=\"font-family: inherit; font-size: 1em;\">Voc\u00ea tamb\u00e9m pode usar o\u00a0<\/span><em>revis\u00e3o<\/em><span style=\"font-family: inherit; font-size: 1em;\">\u00a0para determinar se o cliente recebeu uma nova configura\u00e7\u00e3o.<\/span><\/p>","protected":false},"excerpt":{"rendered":"<p>libcouchbase\u00a02.4.0 is here. It offers large architectural improvements and several new features, improving over previous versions. This blog was originally written for the 2.4.0 DP1 version, it has been modified to reflect the differences between the developer preview and the [&hellip;]<\/p>","protected":false},"author":38,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"ppma_author":[8997],"class_list":["post-1655","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v26.1 (Yoast SEO v26.1.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Introducing libcouchbase 2.4 - The Couchbase Blog<\/title>\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\/introducing-libcouchbase-24-0\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Introducing libcouchbase 2.4\" \/>\n<meta property=\"og:description\" content=\"libcouchbase\u00a02.4.0 is here. It offers large architectural improvements and several new features, improving over previous versions. This blog was originally written for the 2.4.0 DP1 version, it has been modified to reflect the differences between the developer preview and the [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/introducing-libcouchbase-24-0\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2014-12-16T19:35:27+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-05-03T20:26:40+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Mark Nunberg, Software Engineer, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mark Nunberg, Software Engineer, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/\"},\"author\":{\"name\":\"Mark Nunberg, Software Engineer, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/76a75284da32b6f257c8e5e156e6e016\"},\"headline\":\"Introducing libcouchbase 2.4\",\"datePublished\":\"2014-12-16T19:35:27+00:00\",\"dateModified\":\"2017-05-03T20:26:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/\"},\"wordCount\":2254,\"commentCount\":3,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"articleSection\":[\"Uncategorized\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/\",\"name\":\"Introducing libcouchbase 2.4 - The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2014-12-16T19:35:27+00:00\",\"dateModified\":\"2017-05-03T20:26:40+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Introducing libcouchbase 2.4\"}]},{\"@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\/76a75284da32b6f257c8e5e156e6e016\",\"name\":\"Mark Nunberg, Software Engineer, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/895cad0986a0ab674fda857b6ba71ce0\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/d5a465565eb8a3990192957806a9bc2989ba9f52a5f953d988b5e8afff3b6dc7?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/d5a465565eb8a3990192957806a9bc2989ba9f52a5f953d988b5e8afff3b6dc7?s=96&d=mm&r=g\",\"caption\":\"Mark Nunberg, Software Engineer, Couchbase\"},\"description\":\"Mark Nunberg is a software engineer working at Couchbase. He maintains the C client library (libcouchbase) as well as the Python client. He also developed the Perl client (for use at his previous company) - which initially led him to working at Couchbase. Prior to joining Couchbase, he worked on distributed and high performance routing systems at an eCommerce analytics firm. Mark studied Linguistics at the Hebrew University of Jerusalem.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/mark-nunberg\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Introducing libcouchbase 2.4 - The Couchbase Blog","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\/introducing-libcouchbase-24-0\/","og_locale":"pt_BR","og_type":"article","og_title":"Introducing libcouchbase 2.4","og_description":"libcouchbase\u00a02.4.0 is here. It offers large architectural improvements and several new features, improving over previous versions. This blog was originally written for the 2.4.0 DP1 version, it has been modified to reflect the differences between the developer preview and the [&hellip;]","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/introducing-libcouchbase-24-0\/","og_site_name":"The Couchbase Blog","article_published_time":"2014-12-16T19:35:27+00:00","article_modified_time":"2017-05-03T20:26:40+00:00","og_image":[{"width":1800,"height":630,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2022\/11\/couchbase-nosql-dbaas.png","type":"image\/png"}],"author":"Mark Nunberg, Software Engineer, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Mark Nunberg, Software Engineer, Couchbase","Est. reading time":"11 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/"},"author":{"name":"Mark Nunberg, Software Engineer, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/76a75284da32b6f257c8e5e156e6e016"},"headline":"Introducing libcouchbase 2.4","datePublished":"2014-12-16T19:35:27+00:00","dateModified":"2017-05-03T20:26:40+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/"},"wordCount":2254,"commentCount":3,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","articleSection":["Uncategorized"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/","url":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/","name":"Introducing libcouchbase 2.4 - The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2014-12-16T19:35:27+00:00","dateModified":"2017-05-03T20:26:40+00:00","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/introducing-libcouchbase-24-0\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Introducing libcouchbase 2.4"}]},{"@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\/76a75284da32b6f257c8e5e156e6e016","name":"Mark Nunberg, engenheiro de software, Couchbase","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/895cad0986a0ab674fda857b6ba71ce0","url":"https:\/\/secure.gravatar.com\/avatar\/d5a465565eb8a3990192957806a9bc2989ba9f52a5f953d988b5e8afff3b6dc7?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d5a465565eb8a3990192957806a9bc2989ba9f52a5f953d988b5e8afff3b6dc7?s=96&d=mm&r=g","caption":"Mark Nunberg, Software Engineer, Couchbase"},"description":"Mark Nunberg \u00e9 um engenheiro de software que trabalha na Couchbase. Ele mant\u00e9m a biblioteca do cliente em C (libcouchbase), bem como o cliente em Python. Ele tamb\u00e9m desenvolveu o cliente Perl (para uso em sua empresa anterior), o que o levou inicialmente a trabalhar no Couchbase. Antes de ingressar no Couchbase, ele trabalhou em sistemas de roteamento distribu\u00eddos e de alto desempenho em uma empresa de an\u00e1lise de com\u00e9rcio eletr\u00f4nico. Mark estudou Lingu\u00edstica na Universidade Hebraica de Jerusal\u00e9m.","url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/mark-nunberg\/"}]}},"authors":[{"term_id":8997,"user_id":38,"is_guest":0,"slug":"mark-nunberg","display_name":"Mark Nunberg, Software Engineer, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/d5a465565eb8a3990192957806a9bc2989ba9f52a5f953d988b5e8afff3b6dc7?s=96&d=mm&r=g","author_category":"","last_name":"Nunberg","first_name":"Mark","job_title":"","user_url":"","description":"Mark Nunberg \u00e9 um engenheiro de software que trabalha na Couchbase. Ele mant\u00e9m a biblioteca do cliente em C (libcouchbase), bem como o cliente em Python. Ele tamb\u00e9m desenvolveu o cliente Perl (para uso em sua empresa anterior), o que o levou inicialmente a trabalhar no Couchbase. Antes de ingressar no Couchbase, ele trabalhou em sistemas de roteamento distribu\u00eddos e de alto desempenho em uma empresa de an\u00e1lise de com\u00e9rcio eletr\u00f4nico. Mark estudou Lingu\u00edstica na Universidade Hebraica de Jerusal\u00e9m."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/1655","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\/38"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=1655"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/1655\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=1655"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=1655"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=1655"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=1655"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}