Enfileirar funções com o Cloud Tasks


As funções de fila de tarefas usam o Google Cloud Tasks para ajudar seu app a executar tarefas demoradas, que consomem muitos recursos ou limitadas por largura de banda de maneira assíncrona e fora do fluxo principal do app.

Por exemplo, imagine que você quer criar backups de um grande conjunto de arquivos de imagem hospedados atualmente em uma API com um limite de taxa. Para fazer o consumo responsável dessa API, precisamos respeitar esses limites. Além disso, esse tipo de job de longa duração pode ser vulnerável a falhas devido a tempos limite e limites de memória.

Para atenuar essa complexidade, crie uma função de fila de tarefas que defina opções básicas de tarefa, como scheduleTime e dispatchDeadline, que seja distribuída para uma fila no Cloud Tasks. O ambiente do Cloud Tasks foi projetado especificamente para garantir um controle de congestionamento e políticas de repetição eficientes para esses tipos de operações.

O SDK do Firebase para Cloud Functions for Firebase v3.20.1 e versões mais recentes interopera com o Firebase Admin SDK v10.2.0 e versões mais recentes para oferecer suporte a funções de fila de tarefas.

O uso de funções de fila de tarefas com o Firebase pode resultar em cobranças pelo processamento do Cloud Tasks. Para mais informações, consulte Preços do Cloud Tasks.

Criar funções da fila de tarefas

Para usar as funções da fila de tarefas, siga este fluxo de trabalho:

  1. Crie uma função de fila de tarefas usando o SDK do Firebase para Cloud Functions.
  2. Acione a função com uma solicitação HTTP para testá-la.
  3. Implante a função usando a CLI do Firebase. Ao implantar a função de fila de tarefas pela primeira vez, a CLI vai criar uma fila de tarefas no Cloud Tasks com opções (limitação de taxa e nova tentativa) especificadas no código-fonte.
  4. Adicione tarefas à fila de tarefas recém-criada, transmitindo parâmetros para configurar uma programação de execução. Para isso, escreva o código usando o Admin SDK e implante-o no Cloud Functions for Firebase.

Escrever funções da fila de tarefas

Use onDispatch para começar a escrever funções da fila de tarefas. Uma parte importante de escrever uma função da fila de tarefas é definir uma configuração de limitação de taxa e nova tentativa por fila. Os exemplos de código desta página têm como base um app que configura um serviço de backup de todas as imagens do site de fotos astronômicas diárias da NASA (link em inglês):

Configurar funções da fila de tarefas

As funções da fila de tarefas têm um conjunto avançado de configurações para controlar com precisão os limites de taxa e o comportamento de repetição de uma fila de tarefas:

exports.backupApod = functions
    .runWith( {secrets: ["NASA_API_KEY"]})
    .tasks.taskQueue({
      retryConfig: {
        maxAttempts: 5,
        minBackoffSeconds: 60,
      },
      rateLimits: {
        maxConcurrentDispatches: 6,
      },
    }).onDispatch(async (data) => {
  • retryConfig.maxAttempts=5: cada tarefa na fila é repetida automaticamente até cinco vezes. Isso nos ajuda a reduzir falhas transitórias, como erros de rede, ou a interrupção temporária de um serviço externo e dependente.
  • retryConfig.minBackoffSeconds=60: cada tarefa é executada novamente após um intervalo mínimo de 60 segundos. Com isso, temos um grande buffer entre cada tentativa, e não há pressa para realizar as cinco tentativas muito rapidamente.
  • rateLimits.maxConcurrentDispatch=6: são enviadas, no máximo, seis tarefas em um determinado momento. Isso ajuda a garantir um fluxo estável de solicitações para a função, além de reduzir o número de instâncias ativas e inicializações a frio.

Testar funções da fila de tarefas

Na maioria dos casos, o emulador do Cloud Functions é a melhor maneira de testar funções de fila de tarefas. Consulte a documentação do pacote de emuladores para saber como fazer a instrumentação do app para a emulação de funções de fila de tarefas.

Além disso, as funções de fila de tarefas são expostas como funções HTTP simples no Firebase Local Emulator Suite. Para testar uma função de tarefa emulada, envie uma solicitação HTTP POST com um payload de dados json:

 # start the Firebase Emulators
 firebase emulators:start

 # trigger the emulated task queue function
 curl \
  -X POST                                            # An HTTP POST request...
  -H "content-type: application/json" \              # ... with a JSON body
  http://localhost:$PORT/$PROJECT_ID/$REGION/$NAME \ # ... to function url
  -d '{"data": { ... some data .... }}'              # ... with JSON encoded data

Implantar funções da fila de tarefas

Implante a função da fila de tarefas usando a CLI do Firebase:

$ firebase deploy --only functions:backupApod

Ao implantar uma função de fila de tarefas pela primeira vez, a CLI cria uma fila de tarefas no Cloud Tasks com opções (limitação de taxa e nova tentativa) especificadas no código-fonte.

Se você encontrar erros de permissão ao implantar funções, verifique se os papéis do IAM apropriados estão atribuídos ao usuário que executa os comandos de implantação.

Enfileirar funções da fila de tarefas

As funções de fila de tarefas podem ser enfileiradas no Cloud Tasks a partir de um ambiente de servidor confiável, como o Cloud Functions for Firebase, usando o Firebase Admin SDK para Node.js. Se você não tem experiência com Admin SDKs, consulte Adicionar o Firebase a um servidor para saber mais.

Em um fluxo típico, o Admin SDK cria uma tarefa e a enfileira no Cloud Tasks, definindo esta configuração para ela:

exports.enqueueBackupTasks = functions.https.onRequest(
async (_request, response) => {
  const queue = getFunctions().taskQueue("backupApod");
  const enqueues = [];
  for (let i = 0; i <= 10; i += 1) {
    // Enqueue each task with i*60 seconds delay. Our task queue function
    // should process ~1 task/min.
    const scheduleDelaySeconds = i * 60 
    enqueues.push(
        queue.enqueue(
          { id: `task-${i}` },
          {
            scheduleDelaySeconds,
            dispatchDeadlineSeconds: 60 * 5 // 5 minutes
          },
        ),
    );
  }
  await Promise.all(enqueues);
  response.sendStatus(200);

});
  • scheduleDelaySeconds: o exemplo de código tenta distribuir a execução das tarefas associando um atraso de N minutos à Nª tarefa. Isso se traduz no acionamento de aproximadamente 1 tarefa/minuto. Também é possível usar scheduleTime para que o Cloud Tasks acione uma tarefa em um horário específico.
  • dispatchDeadlineSeconds: o tempo máximo que o Cloud Tasks vai aguardar a conclusão de uma tarefa. O Cloud Tasks vai tentar realizar a tarefa novamente de acordo com a configuração de nova tentativa da fila ou até que esse prazo seja atingido. No exemplo, a fila é configurada para tentar realizar a tarefa novamente até cinco vezes, mas a tarefa é cancelada automaticamente se todo o processo (incluindo novas tentativas) levar mais de cinco minutos.

Solução de problemas

Cloud Tasks">Ativar a geração de registros do Cloud Tasks

Os registros do Cloud Tasks contêm informações de diagnóstico úteis, como o status da solicitação associada a uma tarefa. Por padrão, os registros do Cloud Tasks estão desativados devido ao grande volume de registros que podem ser gerados no projeto. Recomendamos ativar os registros de depuração enquanto você desenvolve e depura ativamente as funções da fila de tarefas. Consulte Como ativar a geração de registros.

Permissões do IAM

É possível encontrar erros PERMISSION DENIED ao enfileirar tarefas ou quando o Cloud Tasks tenta invocar as funções de fila de tarefas. Verifique se o projeto tem as seguintes vinculações do IAM:

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudtasks.enqueuer
  • A identidade usada para enfileirar tarefas para o Cloud Tasks precisa de permissão para usar a conta de serviço associada a uma tarefa no Cloud Tasks.

    No exemplo, é a conta de serviço padrão do App Engine.

Consulte a documentação do Google Cloud IAM para saber como adicionar a conta de serviço padrão do App Engine como usuário da conta de serviço padrão do App Engine.

gcloud functions add-iam-policy-binding $FUNCTION_NAME \
  --region=us-central1 \
  --member=serviceAccount:${PROJECT_ID}@appspot.gserviceaccount.com \
  --role=roles/cloudfunctions.invoker