Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Procurando um emulador para o Cloud Tasks?

By Joshua FoxAug 10, 20205 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

Conheça um emulador de Tasks simples que facilita o deploy e o debug.

Quando você desenvolve uma aplicação que usa o Cloud Tasks (um web app, por exemplo), precisa enxergar o que acontece com suas Tasks: como elas são agendadas, entregues e processadas por um task handler. Mas, embora seja um pedido recorrente da comunidade, o Google não oferece um emulador para o Cloud Tasks como faz com o Datastore ou o PubSub.

Meu novo Cloud Tasks In-Process Emulator em Python resolve isso. Se você está sem paciência e quer usar agora, pule direto para o "Quick Start" abaixo.

Como desenvolver para o Cloud Tasks

Você tem quatro opções:

  1. Usar o serviço real do Cloud Tasks.
  2. Usar um emulador rodando em localhost que expõe a mesma interface HTTP do Cloud Tasks.
  3. Pular essa parte: não tratar as tasks. Você pode deixar a criação da task falhar silenciosamente ou disparar tasks sem nenhum handler definido.
  4. Usar um emulador in-process. Injete-o em desenvolvimento e mantenha uma implementação baseada no Cloud Tasks nos sistemas em produção.

Minha recomendação:

  • Um emulador in-process em desenvolvimento
  • O Cloud Tasks de verdade para testes de integração na nuvem
  • Deixar o Cloud Tasks de fora dos testes unitários.

Vamos ver o porquê.

As vantagens do in-process

Debugging

Em desenvolvimento, você quer saber onde cada task está e o que ela contém. Com o emulador rodando in-process, dá para fazer isso pelo seu próprio debugger, pausando a fila e inspecionando os valores.

Simples é bom

O código deste emulador foi mantido bem enxuto, contemplando apenas a criação e o tratamento de tasks. Isso é proposital: uma base de código mais simples (aqui, com menos de 100 linhas) ajuda muito na hora do debug.

Além disso, com um produto em alpha — e todos os emuladores do Cloud Tasks, incluindo este, estão em alpha — é bom ter a tranquilidade de manter todo o código sob seu controle direto, para conseguir depurar rápido e até editá-lo.

Para uma funcionalidade mais ampla e testes mais realistas, eu usaria o Cloud Tasks de verdade, em uma aplicação rodando na nuvem.

Facilidade de uso

Outros emuladores do Cloud Tasks, como o gcloud-tasks-emulator da Potato London e o cloud-tasks-emulator de Aert van de Hulsbeek, rodam em localhost e têm a vantagem de expor a mesma API do serviço na nuvem; basta trocar o endpoint. Outra vantagem: código em qualquer linguagem consegue chamar esses emuladores, o que não rola com o emulador in-process.

Por outro lado, eles trazem o ônus de mais um processo para gerenciar: subir antes de cada sessão de desenvolvimento e ficar de olho se travou ou congelou. E, embora dê para depurá-los rodando em um debugger, isso provavelmente não faz parte do seu fluxo principal de desenvolvimento.

Não perca suas Tasks

Você pode disparar tasks para o Cloud Tasks e nunca tratá-las, ou então deixar a criação falhar silenciosamente. Funciona bem se o seu fluxo principal de desenvolvimento não envolve tratar as tasks: por exemplo, quando elas são tratadas em um microsserviço separado, sob responsabilidade de outro time. Também funciona bem para testes unitários, já que eles costumam não ser usados para testar processos assíncronos distribuídos — esse é papel dos testes de integração.

Mas, se você quer ver o que de fato acontece com suas tasks e como o callback as processa, vai precisar de algum tipo de emulador.

Desenvolva com a nuvem, ou sem ela

Para um fluxo end-to-end completo, dá para usar o Cloud Tasks real na sua máquina de desenvolvimento, com a mesma API e as mesmas funcionalidades do sistema em produção. Funciona bem para testes de integração rodados na nuvem.

Só que, para fazer isso na máquina de desenvolvimento, você vai precisar estar sempre com conexão de rede e configurar um proxy como o ngrok para que o Google Cloud Platform alcance sua máquina local (como mostrado aqui). Usar a API real do Cloud Tasks também exige filas reais, ou seja, ou você tem um projeto Google Cloud próprio, ou precisa gerenciar as filas para que cada desenvolvedor tenha o seu próprio conjunto.

Isso também quer dizer que, para depurar até um processo simples na sua máquina, você acaba indo parar no Cloud Console atrás de mais informações. No meu caso, prefiro pular essa configuração e manter o debug dentro do meu processo.

Recursos e limitações

Este projeto cobre a funcionalidade que você normalmente usa em desenvolvimento: criar uma task e, em seguida, tratá-la em um callback.

Por outro lado, por causa da preferência pela simplicidade mencionada acima, ele não cobre outros recursos, como:

  • Gerenciamento de filas, incluindo criar, deletar, esvaziar, pausar e retomar filas. (Quando você cria uma task, a fila é criada automaticamente, se ainda não existir.)
  • Limites de taxa e retries.
  • Deduplicação e exclusão de tasks.

Se quiser ver novos recursos (e se forem simples o suficiente para justificar a complexidade extra), abra Pull Requests ou Issues no GitHub.

Quick Start

Para usar este emulador, basta copiar o emulator.py para o seu código — você pode até copiar e colar o código desse arquivo direto do GitHub — e pronto.

Crie um objeto Emulator e passe uma função de callback, que vai receber os payloads das tasks que você criar. Depois, para enviar tasks, chame o método Emulator.create_task. Você pode escolher o nome da fila e também o horário agendado para a entrega.

Exemplo de uso

No projeto, você pode ver o emulator.py em ação dentro de um webapp simples. Inicie-o rodando local_server.py. Depois, acesse http://127.0.0.1:8080 (ou clique no link que vai aparecer no console) e uma task será criada. A task será tratada (impressa na saída padrão), conforme o agendamento, três segundos depois.

Se você é xiita de higiene de código e quer manter a base de produção livre do emulador — deixando o emulator.py de fora do deploy —, este exemplo mostra como. No local_server.py, usado em desenvolvimento, injetamos um Emulator. Já em um servidor em produção, onde nenhum Emulator desse tipo é injetado, um novo CloudTasksAccessor é criado e invoca a API real do Cloud Tasks, deixando o código do servidor (main.py) livre de qualquer código do emulador.