This page describes how to create a task handler, the code that handles a push
task. App Engine executes tasks by sending HTTP requests to your application.
You must provide a request handler to execute your task code. The mapping from
the request URL to the code is declared in your service's
like any other request handler. Because you control how to map task requests to
a handler, you're free to organize your task handlers. If your application
processes many different kinds of tasks, you can add all the handlers to a
single service, or you can distribute them among multiple services.
Writing a push task request handler
The Task Queue service creates an HTTP header and sends it to an instance of the
worker service specified by the task's target. The task's URL is appended to the
request's URL, so the worker can select the appropriate handler for the task.
App Engine sends Task Queue requests from the IP address
Your handler does not need to be written in the same language that created and enqueued the task if you write it in a separate service.
When you write you handler, follow these guidelines:
The code should return an HTTP status code within the range 200–299 to indicate success. Any other code indicates that the task failed.
Push tasks have a fixed completion deadline that depends on the scaling type of the service that's running them. Automatic scaling services must finish before 10 minutes have elapsed. Manual and basic scaling services can run up to 24 hours. If your handler misses the deadline, the Task Queue service assumes the failed and will retry it.
When a task's execution time nears the deadline, App Engine raises a
DeadlineExceededError(from the module
google.appengine.runtime) before the deadline is reached, so you can save your work or log whatever progress was made.
It is important to consider whether the handler is idempotent. App Engine's Task Queue API is designed to provide "at least once" delivery; that is, if a task is successfully added, App Engine will deliver it at least once. Note that in some rare circumstances, multiple task execution is possible, so your code must ensure that there are no harmful side-effects of repeated execution.
The following example demonstrates retrieving an integer value from a request and adding the value to a counter that is maintained in 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)
The mapping from the task's url
/update-counter to the class
UpdateCounterHandler is done inside
worker.yaml file creates a service named "worker" and adds the worker code
to it. Note that the handler's URL is secure
because it specifies
runtime: python27 api_version: 1 threadsafe: true module: worker handlers: - url: /.* script: worker.app login: admin
The response is only seen by the Task Queue service to determine if the task succeeded. The service discards the response, so your app will never see it. You should not include any application data in the response. If a task fails, the Task Queue service will retry the task by sending another request.
User-supplied data can be delivered in the request as a query string or as a payload in the request body. Inserting user data is described in Creating Tasks. If the request includes data, the handler must know how it was inserted into the request. The exact code you use to fetch the data from the request depends on the particular web framework you're using.
To test a task handler, sign in as an administrator and visit the handler's URL in your browser.
Reading request headers
A push task HTTP request can include these special headers, which contain task-specific information your handler might want to use:
||The name of the queue (possibly "default" for the default push queue).|
||The name of the task, or a system-generated unique ID if no name was specified.|
||The number of times this task has been retried. For the first attempt, this value is
||The number of times this task has previously failed during the execution phase. This number does not include failures due to a lack of available instances.|
||The target execution time of the task, specified in seconds since January 1st 1970.|
||Indicates that a task running on a manual or basic scaled service fails immediately instead of waiting in a pending queue.|
These headers are set internally by App Engine: If an external user request attempts to set these headers, they are removed. Therefore, if your request handler finds any of these headers in a request, that task queue request is guaranteed to be valid.
Headers are not removed when your app is running in the development server, or when a request is sent by a logged in administrator of the application.
Securing task handler URLs
If a task performs sensitive operations (such as modifying data), you might want to secure its worker URL to prevent a malicious external user from calling it directly. You can prevent users from accessing task URLs by restricting access to App Engine administrators. Task requests themselves are issued by App Engine and can always target restricted URL.
You can restrict a URL by adding the
element to the handler configuration in your
handlers: - url: /your-task script: worker.app login: admin
- Learn how to delete tasks