Crea controladores de tareas

En esta página se explica cómo crear un controlador de tareas, el código que controla una tarea de aplicaciones en cola. Debes proporcionar un controlador de solicitud a fin de procesar la tarea. Mapear una URL de solicitud al controlador correspondiente se declara en el app.yaml del servicio, al igual que cualquier otro controlador de solicitudes. Debido a que controlas cómo se asignan las solicitudes de tareas al controlador, puedes elegir cómo organizar los controladores de tareas. Si la aplicación procesa muchos tipos de tareas diferentes, puedes agregar todos los controladores a un solo servicio o distribuirlos en varios servicios.

Cómo escribir un controlador de solicitudes de tarea de aplicaciones en cola

En la cola, el servicio de lista de tareas en cola crea un encabezado HTTP y lo envía a una instancia del servicio de trabajador especificado por el destino de la tarea. Las solicitudes de lista de tareas en cola se envían desde la dirección IP 0.1.0.2.

Si tu controlador está en un servicio independiente, no es necesario que esté escrito en el mismo lenguaje con el que se creó y puso en cola la tarea.

Sigue estos lineamientos cuando escribas el controlador:

  • El código debe mostrar un código de estado HTTP dentro de un rango de 200 a 299 para indicar que tuvo éxito. Cualquier otro código indicará que la tarea tuvo un error.

  • Las tareas de aplicaciones en cola tienen un plazo de finalización que depende del tipo de escalamiento del servicio que las ejecuta. Los servicios de escalamiento automático deben finalizar su tarea en un plazo de 10 minutos. Los servicios de escalamiento manual y básico pueden ejecutarse hasta por 24 horas. Si el controlador no se adhiere al plazo, el servicio de la lista de tareas en cola entiende que la tarea tuvo un error y la reintenta.

    Cuando el tiempo de ejecución de una tarea se acerca al plazo de finalización, App Engine genera un DeadlineExceededError (desde el google.appengine.runtime del módulo) antes de que se cumpla el plazo para que puedas guardar tu trabajo o registrar el progreso realizado.

  • El controlador debe ser idempotente. La API de la lista de tareas en cola de App Engine está diseñada para brindar una entrega de "al menos una vez"; es decir, si una tarea se agrega con éxito, App Engine la entregará al controlador al menos una vez. Ten en cuenta que, en algunas circunstancias excepcionales, es posible la ejecución de varias tareas, por lo que tu código debe garantizar que la ejecución repetida no causará efectos secundarios dañinos.

En el ejemplo siguiente se muestra cómo recuperar un valor de número entero de una solicitud y cómo agregar el valor a un contador que se mantiene en 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)

La asignación de la URL /update-counter de la tarea a la clase UpdateCounterHandler se realiza dentro de WSGIApplication.

El archivo worker.yaml crea un servicio llamado “worker” y le agrega el código de trabajador. Ten en cuenta que la URL del controlador es segura porque especifica login:admin:

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

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

La lista de tareas en cola utiliza el código HTTP en la respuesta del controlador a fin de determinar si la tarea tuvo éxito. Solo el servicio de la lista de tareas en cola ve la respuesta del controlador para determinar si la tarea se realizó con éxito. La cola ignora todos los otros campos de la respuesta. Luego, el servicio descarta la respuesta. La aplicación de origen nunca recibe ningún tipo de datos. Si una tarea falla, el servicio de la lista de tareas en cola envía otra solicitud para reintentar la tarea.

Los datos suministrados por el usuario pueden entregarse al controlador en la solicitud como una string de consulta o como una carga útil en el cuerpo de la solicitud. La inserción de datos del usuario se describe en Crea tareas. Si la solicitud incluye datos, el controlador debe saber cómo se insertaron en la solicitud. El código exacto que uses para recuperar los datos de la solicitud depende del marco de trabajo web particular que uses.

Si deseas poner a prueba un controlador de tareas, accede como administrador y visita la URL del controlador en tu navegador.

Cómo leer encabezados de solicitud

Una solicitud HTTP de tarea de aplicaciones en cola tiene encabezados especiales establecidos por App Engine, que contienen información específica de la tarea que puede utilizar el controlador.

Si estos encabezados están presentes en una solicitud de usuario externo a la aplicación, se eliminan y reemplazan. La única excepción es para solicitudes de administradores que hayan accedido a la aplicación y que tengan permitido establecer encabezados con fines de prueba. Por otro lado, los encabezados no se quitan cuando la aplicación se está ejecutando en el servidor de desarrollo.

Las solicitudes de la lista de tareas en cola siempre contendrán los siguientes encabezados:

Encabezado Descripción
X-Appengine-QueueName El nombre de la cola (es posible que sea "default" para la lista de aplicaciones en cola predeterminada).
X-Appengine-TaskName El nombre de la tarea, o un ID único generado por el sistema si no se especificó el nombre.
X-Appengine-TaskRetryCount La cantidad de veces que se reintentó esta tarea. Si es el primer intento, el valor es 0. Este número incluye los intentos en los que la tarea falló debido a la falta de instancias disponibles y nunca llegó a la fase de ejecución.
X-Appengine-TaskExecutionCount La cantidad de veces anteriores que esta tarea falló durante la fase de ejecución. Este número no incluye las fallas ocasionadas por la falta de instancias disponibles.
X-Appengine-TaskETA El plazo de ejecución objetivo de la tarea, especificado en segundos desde el 1 de enero de 1970.

Si el controlador de solicitudes encuentra alguno de los encabezados antes mencionados, podrá confiar en que la solicitud es de la lista de tareas en cola.

Además, las solicitudes de la lista de tareas en cola pueden contener los siguientes encabezados:

Encabezado Descripción
X-Appengine-TaskPreviousResponse El código de respuesta HTTP del reintento anterior.
X-Appengine-TaskRetryReason La razón por la que se volvió a intentar la tarea.
X-Appengine-FailFast Indica que una tarea que se está ejecutando falla de inmediato si una instancia existente no está disponible.

Cómo asegurar las URL del controlador de tareas

Si una tarea lleva a cabo operaciones confidenciales (como modificar datos), te recomendamos asegurar la URL del controlador a fin de evitar que un usuario externo malicioso la llame directamente. Para evitar que los usuarios accedan a las URL de las tareas, puedes restringir el acceso a los administradores de App Engine. App Engine emite las solicitudes de tareas y siempre pueden dirigirse a una URL restringida.

Puedes restringir una URL si agregas el elemento login: admin a la configuración del controlador en el archivo app.yaml.

Por ejemplo:

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

¿Qué sigue?