Gerenciar funções


Você pode implantar, excluir e modificar funções usando comandos da CLI do Firebase ou definindo opções de tempo de execução no código-fonte das funções.

Implantar funções

Para implantar funções, execute este comando Firebase CLI:

firebase deploy --only functions

Por padrão, a CLI do Firebase implanta todas as funções dentro da sua fonte ao mesmo tempo. Se o seu projeto contiver mais de cinco funções, recomendamos que você use o sinalizador --only com nomes de funções específicos para implantar apenas as funções que você editou. A implantação de funções específicas dessa forma acelera o processo de implantação e ajuda a evitar atingir cotas de implantação. Por exemplo:

firebase deploy --only functions:addMessage,functions:makeUppercase

Ao implantar um grande número de funções, você poderá exceder a cota padrão e receber mensagens de erro HTTP 429 ou 500. Para resolver isso, implante funções em grupos de 10 ou menos.

Consulte a referência da CLI do Firebase para ver a lista completa de comandos disponíveis.

Por padrão, a CLI do Firebase procura na pasta functions/ o código-fonte. Se preferir, você pode organizar funções em bases de código ou em vários conjuntos de arquivos.

Excluir funções

Você pode excluir funções implantadas anteriormente destas maneiras:

  • explicitamente na CLI do Firebase com functions:delete
  • explicitamente no console do Google Cloud .
  • implicitamente , removendo a função da origem antes da implantação.

Todas as operações de exclusão solicitam confirmação antes de remover a função da produção.

A exclusão explícita de funções na CLI do Firebase oferece suporte a vários argumentos, bem como grupos de funções, e permite especificar uma função em execução em uma região específica. Além disso, você pode substituir o prompt de confirmação.

# Delete all functions that match the specified name in all regions.
firebase functions:delete myFunction
# Delete a specified function running in a specific region.
firebase functions:delete myFunction --region us-east-1
# Delete more than one function
firebase functions:delete myFunction myOtherFunction
# Delete a specified functions group.
firebase functions:delete groupA
# Bypass the confirmation prompt.
firebase functions:delete myFunction --force

Com a exclusão implícita de funções, firebase deploy analisa sua origem e remove da produção todas as funções que foram removidas do arquivo.

Modifique o nome, região ou gatilho de uma função

Se você estiver renomeando ou alterando as regiões ou o gatilho para funções que manipulam o tráfego de produção, siga as etapas nesta seção para evitar a perda de eventos durante a modificação. Antes de seguir essas etapas, primeiro certifique-se de que sua função seja idempotente , pois tanto a nova versão quanto a versão antiga de sua função estarão em execução ao mesmo tempo durante a alteração.

Renomear uma função

Para renomear uma função, crie uma nova versão renomeada da função em sua origem e execute dois comandos de implantação separados. O primeiro comando implanta a função recém-nomeada e o segundo comando remove a versão implantada anteriormente. Por exemplo, se você tiver uma função Node.js chamada webhook que gostaria de alterar para webhookNew , revise o código da seguinte maneira:

// before
const functions = require('firebase-functions');

exports.webhook = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

// after
const functions = require('firebase-functions');

exports.webhookNew = functions.https.onRequest((req, res) => {
    res.send("Hello");
});

Em seguida, execute os seguintes comandos para implantar a nova função:

# Deploy new function called webhookNew
firebase deploy --only functions:webhookNew

# Wait until deployment is done; now both webhookNew and webhook are running

# Delete webhook
firebase functions:delete webhook

Alterar a região ou regiões de uma função

Se estiver alterando as regiões especificadas para uma função que lida com o tráfego de produção, você poderá evitar a perda de eventos executando estas etapas na ordem:

  1. Renomeie a função e altere sua região ou regiões conforme desejado.
  2. Implante a função renomeada, o que resulta na execução temporária do mesmo código em ambos os conjuntos de regiões.
  3. Exclua a função anterior.

Por exemplo, se você tem uma função chamada webhook que está atualmente na região de funções padrão de us-central1 e deseja migrá-la para asia-northeast1 , primeiro você precisa modificar seu código-fonte para renomear a função e revisar a região .

// before
const functions = require('firebase-functions');

exports.webhook = functions
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

// after
const functions = require('firebase-functions');

exports.webhookAsia = functions
    .region('asia-northeast1')
    .https.onRequest((req, res) => {
            res.send("Hello");
    });

Em seguida, implante executando:

firebase deploy --only functions:webhookAsia

Agora existem duas funções idênticas em execução: webhook está em execução em us-central1 e webhookAsia está em execução em asia-northeast1 .

Em seguida, exclua webhook :

firebase functions:delete webhook

Agora há apenas uma função - webhookAsia , que está sendo executada em asia-northeast1 .

Alterar o tipo de gatilho de uma função

À medida que você desenvolve sua implantação do Cloud Functions para Firebase ao longo do tempo, pode ser necessário alterar o tipo de gatilho de uma função por vários motivos. Por exemplo, você pode querer mudar de um tipo de evento do Firebase Realtime Database ou do Cloud Firestore para outro tipo.

Não é possível alterar o tipo de evento de uma função apenas alterando o código-fonte e executando firebase deploy . Para evitar erros, altere o tipo de gatilho de uma função com este procedimento:

  1. Modifique o código-fonte para incluir uma nova função com o tipo de gatilho desejado.
  2. Implante a função, o que resulta na execução temporária das funções antigas e novas.
  3. Exclua explicitamente a função antiga da produção usando a CLI do Firebase.

Por exemplo, se você tinha uma função Node.js chamada objectChanged que tem o tipo de evento onChange herdado e gostaria de alterá-la para onFinalize , primeiro renomeie a função e edite-a para ter o tipo de evento onFinalize .

// before
const functions = require('firebase-functions');

exports.objectChanged = functions.storage.object().onChange((object) => {
    return console.log('File name is: ', object.name);
});

// after
const functions = require('firebase-functions');

exports.objectFinalized = functions.storage.object().onFinalize((object) => {
    return console.log('File name is: ', object.name);
});

Em seguida, execute os seguintes comandos para criar a nova função primeiro, antes de excluir a função antiga:

# Create new function objectFinalized
firebase deploy --only functions:objectFinalized

# Wait until deployment is done; now both objectChanged and objectFinalized are running

# Delete objectChanged
firebase functions:delete objectChanged

Definir opções de tempo de execução

O Cloud Functions para Firebase permite selecionar opções de tempo de execução, como a versão do tempo de execução do Node.js e o tempo limite por função, a alocação de memória e instâncias de função mínima/máxima.

Como prática recomendada, essas opções (exceto para a versão Node.js) devem ser definidas em um objeto de configuração dentro do código da função. Este objeto RuntimeOptions é a fonte da verdade para as opções de tempo de execução da sua função e substituirá as opções definidas por qualquer outro método (como por meio do console do Google Cloud ou da CLI gcloud).

Se o seu fluxo de trabalho de desenvolvimento envolver a configuração manual de opções de tempo de execução por meio do console do Google Cloud ou da CLI gcloud e você não quiser que esses valores sejam substituídos em cada implantação, defina a opção preserveExternalChanges como true . Com esta opção definida como true , o Firebase mescla as opções de tempo de execução definidas no seu código com as configurações da versão atualmente implantada da sua função com a seguinte prioridade:

  1. A opção está definida no código de funções: substituir alterações externas.
  2. A opção está definida como RESET_VALUE no código de funções: substituir alterações externas pelo valor padrão.
  3. A opção não está definida no código de funções, mas está definida na função implantada atualmente: use a opção especificada na função implementada.

Usar a opção preserveExternalChanges: true não é recomendado para a maioria dos cenários porque seu código não será mais a fonte completa de verdade para opções de tempo de execução para suas funções. Se você usá-lo, verifique o console do Google Cloud ou use a CLI gcloud para visualizar a configuração completa de uma função.

Definir versão do Node.js.

O SDK do Firebase para Cloud Functions permite uma seleção de tempo de execução do Node.js. Você pode optar por executar todas as funções em um projeto exclusivamente no ambiente de tempo de execução correspondente a uma destas versões suportadas do Node.js:

  • Node.js 20 (visualização)
  • Node.js 18
  • Node.js 16
  • Node.js 14

Para definir a versão do Node.js:

Você pode definir a versão no campo engines no arquivo package.json que foi criado em seu diretório functions/ durante a inicialização. Por exemplo, para usar apenas a versão 18, edite esta linha em package.json :

  "engines": {"node": "18"}

Se você estiver usando o gerenciador de pacotes Yarn ou tiver outros requisitos específicos para o campo engines , poderá definir o tempo de execução do SDK do Firebase para Cloud Functions em firebase.json :

  {
    "functions": {
      "runtime": "nodejs18" // or nodejs14, nodejs16 or nodejs20
    }
  }

A CLI usa o valor definido em firebase.json em preferência a qualquer valor ou intervalo definido separadamente em package.json .

Atualize seu tempo de execução do Node.js.

Para atualizar seu tempo de execução do Node.js:

  1. Certifique-se de que seu projeto esteja no plano de preços Blaze .
  2. Verifique se você está usando o Firebase CLI v11.18.0 ou posterior.
  3. Altere o valor engines no arquivo package.json que foi criado em seu diretório functions/ durante a inicialização. Por exemplo, se você estiver atualizando da versão 16 para a versão 18, a entrada deverá ser semelhante a esta: "engines": {"node": "18"}
  4. Opcionalmente, teste suas alterações usando o Firebase Local Emulator Suite .
  5. Reimplante todas as funções.

Controlar o comportamento de dimensionamento

Por padrão, o Cloud Functions para Firebase dimensiona o número de instâncias em execução com base no número de solicitações recebidas, reduzindo potencialmente para zero instâncias em momentos de tráfego reduzido. No entanto, se seu aplicativo exigir latência reduzida e você quiser limitar o número de inicializações a frio, poderá alterar esse comportamento padrão especificando um número mínimo de instâncias de contêiner a serem mantidas aquecidas e prontas para atender solicitações.

Da mesma forma, você pode definir um número máximo para limitar o dimensionamento de instâncias em resposta às solicitações recebidas. Use esta configuração como uma forma de controlar seus custos ou limitar o número de conexões com um serviço de apoio, como um banco de dados.

Reduza o número de partidas a frio

Para definir o número mínimo de instâncias para uma função no código-fonte, use o método runWith . Este método aceita um objeto JSON em conformidade com a interface RuntimeOptions , que define o valor para minInstances . Por exemplo, esta função define um mínimo de 5 instâncias para se manter aquecido:

exports.getAutocompleteResponse = functions
    .runWith({
      // Keep 5 instances warm for this latency-critical function
      minInstances: 5,
    })
    .https.onCall((data, context) => {
      // Autocomplete a user's search term
    });

Aqui estão algumas coisas a serem consideradas ao definir um valor para minInstances :

  • Se o Cloud Functions para Firebase dimensionar seu aplicativo acima da configuração minInstances , você experimentará uma inicialização a frio para cada instância acima desse limite.
  • As inicializações a frio têm o efeito mais severo em aplicativos com tráfego intenso. Se seu aplicativo tiver tráfego intenso e você definir um valor minInstances alto o suficiente para que as inicializações a frio sejam reduzidas a cada aumento de tráfego, você verá uma latência significativamente reduzida. Para aplicativos com tráfego constante, as inicializações a frio provavelmente não afetarão gravemente o desempenho.
  • Definir instâncias mínimas pode fazer sentido para ambientes de produção, mas geralmente deve ser evitado em ambientes de teste. Para escalar para zero em seu projeto de teste, mas ainda reduzir inicializações a frio em seu projeto de produção, você pode definir minInstances com base na variável de ambiente FIREBASE_CONFIG :

    // Get Firebase project id from `FIREBASE_CONFIG` environment variable
    const envProjectId = JSON.parse(process.env.FIREBASE_CONFIG).projectId;
    
    exports.renderProfilePage = functions
        .runWith({
          // Keep 5 instances warm for this latency-critical function
          // in production only. Default to 0 for test projects.
          minInstances: envProjectId === "my-production-project" ? 5 : 0,
        })
        .https.onRequest((req, res) => {
          // render some html
        });
    

Limite o número máximo de instâncias para uma função

Para definir o máximo de instâncias no código-fonte da função, use o método runWith . Este método aceita um objeto JSON em conformidade com a interface RuntimeOptions , que define valores para maxInstances . Por exemplo, esta função define um limite de 100 instâncias para não sobrecarregar um hipotético banco de dados legado:

exports.mirrorOrdersToLegacyDatabase = functions
    .runWith({
      // Legacy database only supports 100 simultaneous connections
      maxInstances: 100,
    })
    .firestore.document("orders/{orderId}")
    .onWrite((change, context) => {
      // Connect to legacy database
    });

Se uma função HTTP for ampliada até o limite maxInstances , novas solicitações serão enfileiradas por 30 segundos e depois rejeitadas com um código de resposta de 429 Too Many Requests se nenhuma instância estiver disponível até então.

Para saber mais sobre as práticas recomendadas para usar configurações de máximo de instâncias, confira estas práticas recomendadas para usar maxInstances .

Definir tempo limite e alocação de memória

Em alguns casos, suas funções podem ter requisitos especiais para um valor de tempo limite longo ou uma grande alocação de memória. Você pode definir esses valores no Console do Google Cloud ou no código-fonte da função (somente Firebase).

Para definir a alocação de memória e o tempo limite no código-fonte das funções, use o parâmetro runWith introduzido no SDK do Firebase para Cloud Functions 2.0.0. Esta opção de tempo de execução aceita um objeto JSON em conformidade com a interface RuntimeOptions , que define valores para timeoutSeconds e memory . Por exemplo, esta função de armazenamento utiliza 1 GB de memória e expira após 300 segundos:

exports.convertLargeFile = functions
    .runWith({
      // Ensure the function has enough memory and time
      // to process large files
      timeoutSeconds: 300,
      memory: "1GB",
    })
    .storage.object()
    .onFinalize((object) => {
      // Do some complicated things that take a lot of memory and time
    });

O valor máximo para timeoutSeconds é 540 ou 9 minutos. A quantidade de memória concedida a uma função corresponde à CPU alocada para a função, conforme detalhado nesta lista de valores válidos para memory :

  • 128MB – 200 MHz
  • 256MB – 400 MHz
  • 512MB – 800 MHz
  • 1GB – 1,4 GHz
  • 2GB – 2,4 GHz
  • 4GB – 4,8 GHz
  • 8GB – 4,8 GHz

Para definir a alocação de memória e o tempo limite no console do Google Cloud:

  1. No console do Google Google Cloud, selecione Cloud Functions no menu esquerdo.
  2. Selecione uma função clicando em seu nome na lista de funções.
  3. Clique no ícone Editar no menu superior.
  4. Selecione uma alocação de memória no menu suspenso denominado Memória alocada .
  5. Clique em Mais para exibir as opções avançadas e insira um número de segundos na caixa de texto Tempo limite .
  6. Clique em Salvar para atualizar a função.