O problema: “Sem estado” não significa “sem configuração”
O Couchbase Eventing foi intencionalmente criado como um lambda de curta duração e sem estado: reagir a uma mutação, fazer algum trabalho e sair. Esse modelo é limpo - até que sua função de eventos precise de única antes de poder processar com segurança a primeira mutação.
Historicamente, os desenvolvedores contornavam esse problema fazendo um “aquecimento da primeira mutação” dentro do OnUpdate, geralmente com gravações ou contadores seguros para CAS, de modo que apenas um thread carregasse um estado compartilhado. Essa abordagem pode funcionar, mas força você a depender de uma mutação apenas para estabelecer pré-requisitos e empurra as preocupações de configuração para a parte mais quente do caminho do código: o processamento da mutação.
É exatamente por isso que havia a necessidade de um conceito de inicialização sem mutação em Eventing - uma fase de configuração explícita que pode ser executada sem uma mutação inicial e deixar a função pronta antes do início de qualquer trabalho real.
A ideia: uma lista de verificação antes do voo
OnDeploy é um novo manipulador de eventos que executa uma vez quando houver uma função Eventing:
- implantadoou
- retomada (depois de ser pausado)
E, o que é mais importante, é executado antes que qualquer mutação seja processada.
Se você pensar em sua função de Eventing como uma aeronave:
- Sobre a atualização / OnDelete são as operações de voo.
- O OnDeploy é a verificação antes do voo.
- Se a verificação pré-voo falhar, o avião não sai da pista de decolagem.
Esse comportamento de “guardião” é a chave: se OnDeploy falhar, a função reverterá para o estado anterior - protegendo-o de cenários de “lógica mal configurada entra em operação”.
Como funciona: OnDeploy(action)
Se você definir um OnDeploy em seu código de função de evento, ele será chamado uma vez com um ação argumento.
|
1 2 3 |
function OnDeploy(action) { // your setup code } |
Onde:
- action.reason é um deles:
- “implantar”: uma nova implantação da função de eventos
- “currículo”: retomada após uma pausa
- action.delay é:
- 0 em “implantar”
- a duração efetiva da pausa (milissegundos) em “currículo”

Dois importantes trilhos de segurança
- Tempo limite: OnDeploy deve terminar dentro do tempo configurado Tempo limite do OnDeploy (padrão: 60 segundos). Se exceder o tempo limite, não será permitido prosseguir com a implementação da função.
- Semântica fail-fast: Se OnDeploy gera um erro ou falha, nenhuma mutação é processada e a função permanece em seu estado anterior.
Por que isso é importante
O OnDeploy não é apenas “bom ter”. É uma mudança na forma como você pode projetar funções de eventos:
- Primeiro, a correção: Certifique-se de que os pré-requisitos existam antes da execução de qualquer lógica de gravação.
- Menos clichês: Remover os hacks de coordenação de thread do Sobre a atualização.
- Tempo mais rápido para a primeira mutação correta: Aquece os caches uma vez, não por thread.
| Aspecto | Sem OnDeploy | Com o OnDeploy |
| Inicialização | Em OnUpdate (propenso a corridas) | Uma vez, antes das mutações |
| Coordenação da linha | Necessário | Não é necessário |
| Garantia de instalação | Melhor esforço | Garantia de falhas rápidas |
| Segurança na implantação | Possibilidade de falhas silenciosas | Bloqueado se a configuração falhar |
Casos de uso
- Você precisa de uma tabela de pesquisa (preços, taxas de câmbio, configurações) antes de permitir que qualquer mutação atue em dados incompletos.
- Você quer um trabalho recorrente (uma vez por dia, uma vez por hora), mas não quer “fingir” uma mutação apenas para iniciar uma cronômetro.
- Você deseja que a função se recuse a ser executada se os pré-requisitos estiverem ausentes, pois é melhor bloquear a implantação do que produzir silenciosamente gravações erradas.
Exemplo 1: Aqueça uma tabela de pesquisa uma vez e, em seguida, programe uma atualização diária
Cenário
Você enriquece documentos com preços de ações no final do dia. Os preços são obtidos diariamente de uma API REST externa, armazenados em um documento KV e usados por todas as mutações posteriores.
Com o OnDeploy, você pode fazer o aquecimento uma vez, garantida, antes que qualquer mutação seja processada.
Código
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
// Timer Callback: refresh prices daily function RefreshPricesCallback(context) { log("Refreshing stock prices from API"); var response = curl("GET", stock_api_binding, {path: '/api/eod-prices'}); cache_bucket["lookup::eod_prices"] = response.body; // Re-schedule for tomorrow var tomorrow = new Date(); tomorrow.setSeconds(tomorrow.getSeconds() + 86400); // 24 hours createTimer(RefreshPricesCallback, tomorrow, "refresh_prices", {}); } // OnDeploy: initialize price cache once function OnDeploy(action) { log("OnDeploy: reason=" + action.reason); // Fetch initial prices from external API var response = curl("GET", stock_api_binding, {path: '/api/eod-prices'}); cache_bucket["lookup::eod_prices"] = response.body; // Schedule daily refresh timer var tomorrow = new Date(); tomorrow.setSeconds(tomorrow.getSeconds() + 86400); createTimer(RefreshPricesCallback, tomorrow, "refresh_prices", {}); log("Price cache initialized and refresh timer scheduled"); } // OnUpdate: enrich documents with cached prices function OnUpdate(doc, meta) { var prices = cache_bucket["lookup::eod_prices"]; doc.stockPrice = prices[doc.symbol]; doc.enrichedAt = new Date().toISOString(); dst_bucket[meta.id] = doc; } |
As vantagens dessa lógica:
- Nenhuma surpresa do tipo “a primeira mutação faz a configuração”.
- Não há complexidade de cross-thread no interior Sobre a atualização.
- Toda mutação começa com os pré-requisitos em vigor.
Exemplo 2: Tratar a implementação e a retomada de forma diferente com o OnDeploy
Cenário
Às vezes, o trabalho não é “programar o trabalho” - é tornar sua função segura para iniciar (ou segura para reiniciar).
Por exemplo, sua função Eventing pode depender de:
- dados externos (podem ser obtidos por meio de vínculos cURL na primeira implantação) e
- configuração armazenada no Couchbase (que deve ser recarregada após uma pausa)
Essa é uma ótima opção para o OnDeploy, pois permite que você comportamento das filiais com base no ciclo de vida e garantir que sua função esteja pronta antes de processamento de quaisquer mutações.
Código
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function OnDeploy(action) { log('OnDeploy triggered. Reason:', action.reason); switch (action.reason) { case 'deploy': // First-time deployment: fetch initial data needed by the function. log('Bootstrapping: Performing first-time setup...'); bootstrap_external_data(); break; case 'resume': // Function was paused and resumed: refresh any cached settings. log('Configuration changed. Reloading settings...'); reload_config_from_bucket(); break; } } |
Esse padrão mantém a lógica do ciclo de vida explícita e limpa:
- Implementar se torna o momento em que você faz um trabalho de bootstrap único.
- Currículo passa a ser o momento em que você reconcilia/atualiza a configuração depois de fazer uma pausa (action.delay informa quanto tempo você ficou em pausa).
- Seus manipuladores de mutação mantêm o foco na lógica de negócios porque podem presumir que os pré-requisitos já foram atendidos.
Orientação de design: o que não para fazer no OnDeploy
O OnDeploy é poderoso, mas é deliberadamente limitado:
- Mantenha-o curto e determinístico.
- Evite loops de longa duração que possam atrasar a implementação.
- Trate-o como código de infraestrutura: valide os pré-requisitos, inicialize o estado compartilhado, programe o trabalho e saia.
Conclusão
O OnDeploy traz uma mudança fundamental para o Couchbase Eventing: a capacidade de garantir que os pré-requisitos sejam atendidos antes que uma única mutação seja processada. Em vez de espalhar a lógica de inicialização entre os manipuladores de mutação ou depender de hacks de aquecimento propensos a corridas, agora você tem uma única verificação explícita de pré-voo que é executada uma vez e falha rapidamente se algo der errado.
O resultado? Código mais limpo, implementações mais seguras e confiança de que suas funções de Eventing sempre iniciam em um estado reconhecidamente bom.
Pronto para experimentar? O OnDeploy está disponível a partir do Couchbase Server 8.0 e superior. Confira a documentação abaixo para começar e considere quais das suas funções de Eventing existentes poderiam se beneficiar desse padrão.
Referências