Criando manipuladores de tarefas

Esta página descreve como criar um manipulador de tarefas , o código que trata uma tarefa push. Você deve fornecer um manipulador de solicitação para processar a tarefa. O mapeamento do URL da solicitação para o manipulador apropriado é declarado no app.yaml do seu serviço, assim como qualquer outro manipulador de solicitação. Como você controla como mapear solicitações de tarefas para um manipulador, você está livre para organizar seus manipuladores de tarefas. Se seu aplicativo processa muitos tipos diferentes de tarefas, você poderá adicionar todos os manipuladores a um único serviço ou distribuí-los entre vários serviços.

Escrevendo um manipulador de solicitação de tarefa push

Na fila, o serviço Task Queue cria um cabeçalho HTTP e o envia para uma instância do serviço de trabalho especificado pelo destino da tarefa. As solicitações da fila de tarefas são enviadas do endereço IP 0.1.0.2 .

Seu manipulador não precisa ser escrito na mesma linguagem que criou e enfileirou a tarefa se o manipulador estiver em um serviço separado .

Ao escrever seu manipulador, siga estas diretrizes:

  • O código deve retornar um código de status HTTP no intervalo 200–299 para indicar sucesso. Qualquer outro código indica que a tarefa falhou.

  • As tarefas push têm um prazo de conclusão fixo que depende do tipo de escala do serviço que as executa. Os serviços de escalabilidade automática devem terminar antes de decorridos 10 minutos. Os serviços de escalonamento manual e básico podem durar até 24 horas. Se o seu manipulador perder o prazo, o serviço Task Queue assumirá que a tarefa falhou e tentará novamente.

    Quando o tempo de execução de uma tarefa se aproxima do prazo, o App Engine gera um DeadlineExceededError (do módulo google.appengine.runtime ) antes que o prazo seja atingido, para que você possa salvar seu trabalho ou registrar qualquer progresso feito.

  • O manipulador deve ser idempotente . A API Task Queue do App Engine foi projetada para fornecer entrega "pelo menos uma vez"; ou seja, se uma tarefa for adicionada com êxito, o App Engine a entregará a um manipulador pelo menos uma vez. Observe que, em algumas circunstâncias raras, a execução de múltiplas tarefas é possível, portanto, seu código deve garantir que não haja efeitos colaterais prejudiciais da execução repetida.

O exemplo a seguir demonstra a recuperação de um valor inteiro de uma solicitação e a adição do valor a um contador mantido no Cloud Datastore:


from google.appengine.ext import ndb
import webapp2


COUNTER_KEY = 'default counter'


class Counter(ndb.Model):
    count = ndb.IntegerProperty(indexed=False)


class UpdateCounterHandler(webapp2.RequestHandler):
    def post(self):
        amount = int(self.request.get('amount'))

        # This task should run at most once per second because of the datastore
        # transaction write throughput.
        @ndb.transactional
        def update_counter():
            counter = Counter.get_or_insert(COUNTER_KEY, count=0)
            counter.count += amount
            counter.put()

        update_counter()


app = webapp2.WSGIApplication([
    ('/update_counter', UpdateCounterHandler)
], debug=True)

O mapeamento da url /update-counter da tarefa para a classe UpdateCounterHandler é feito dentro de WSGIApplication .

O arquivo worker.yaml cria um serviço chamado "trabalhador" e adiciona o código do trabalhador a ele. Observe que a URL do manipulador é segura porque especifica login:admin :

runtime: python27
api_version: 1
threadsafe: true
service: worker

handlers:
- url: /.*
  script: worker.app
  login: admin

A fila de tarefas usa o código HTTP na resposta do manipulador para determinar se a tarefa foi bem-sucedida. A resposta do manipulador é vista apenas pelo serviço Task Queue e apenas para determinar se a tarefa foi bem-sucedida. A fila ignora todos os outros campos da resposta. Em seguida, o serviço descarta a resposta. O aplicativo de origem nunca recebe nenhum dado. Se uma tarefa falhar, o serviço Task Queue tentará novamente a tarefa enviando outra solicitação.

Os dados fornecidos pelo usuário podem ser entregues ao manipulador na solicitação como uma string de consulta ou como uma carga útil no corpo da solicitação. A inserção de dados do usuário está descrita em Criando Tarefas . Se a solicitação incluir dados, o manipulador deverá saber como eles foram inseridos na solicitação. O código exato que você usa para buscar os dados da solicitação depende da estrutura da web específica que você está usando.

Para testar um gerenciador de tarefas, faça login como administrador e visite o URL do gerenciador em seu navegador.

Lendo cabeçalhos de solicitação

Uma solicitação HTTP de tarefa push tem cabeçalhos especiais definidos pelo App Engine, que contêm informações específicas da tarefa que seu manipulador pode usar.

Se esses cabeçalhos estiverem presentes em uma solicitação de usuário externo ao seu aplicativo, eles serão removidos e substituídos. A única exceção é para solicitações de administradores logados no aplicativo, que têm permissão para definir cabeçalhos para fins de teste. Por outro lado, os cabeçalhos não são removidos quando seu aplicativo está sendo executado no servidor de desenvolvimento.

As solicitações da fila de tarefas sempre conterão os seguintes cabeçalhos:

Cabeçalho Descrição
X-Appengine-QueueName O nome da fila (possivelmente "padrão" para a fila push padrão).
X-Appengine-TaskName O nome da tarefa ou um ID exclusivo gerado pelo sistema, caso nenhum nome tenha sido especificado.
X-Appengine-TaskRetryCount O número de vezes que esta tarefa foi repetida. Para a primeira tentativa, esse valor é 0 . Esse número inclui tentativas em que a tarefa falhou por falta de instâncias disponíveis e nunca chegou à fase de execução.
X-Appengine-TaskExecutionCount O número de vezes que esta tarefa falhou anteriormente durante a fase de execução. Este número não inclui falhas por falta de instâncias disponíveis.
X-Appengine-TaskETA O tempo de execução alvo da tarefa, especificado em segundos desde 1º de janeiro de 1970.

Se o seu manipulador de solicitação encontrar algum dos cabeçalhos listados acima, ele poderá confiar que a solicitação é uma solicitação de fila de tarefas.

Além disso, as solicitações do Task Queue podem conter os seguintes cabeçalhos:

Cabeçalho Descrição
X-Appengine-TaskPreviousResponse O código de resposta HTTP da nova tentativa anterior.
X-Appengine-TaskRetryReason O motivo para tentar novamente a tarefa.
X-Appengine-FailFast Indica que uma tarefa em execução falhará imediatamente se uma instância existente não estiver disponível .

Protegendo URLs do manipulador de tarefas

Se uma tarefa executar operações confidenciais (como modificação de dados), talvez você queira proteger a URL do manipulador para evitar que um usuário externo mal-intencionado a chame diretamente. Você pode impedir que os usuários acessem URLs de tarefas restringindo o acesso aos administradores do App Engine . As próprias solicitações de tarefa são emitidas pelo App Engine e sempre podem direcionar um URL restrito.

Você pode restringir um URL adicionando o elemento login: admin à configuração do manipulador em seu arquivo app.yaml .

Por exemplo:

handlers:
- url: /your-task
  script: worker.app
  login: admin

O que vem a seguir