How to use the Deferred Library and TaskQueues

Posted by Raj Chohan on 11/25/13 2:12 PM

Developer Innovation

Thanks to the Python Task Queue API and Deferred library it’s easier than ever to conduct work behind the scenes of your app. 

The Deferred library allows you to by pass all of the work in setting up dedicated task handlers and serializing/deserializing your parameters by exposing the simple function Deferred.defer(). Below we’ll walk you through a simple example of using the Task Queue API and Deferred library. Our example uses webapp2 for a web server interface gateway (WSIG), jinja2 for simple templating and the Mail API for sending email.

Our example app will take a user submitted email address and send the provided email address an email at a predetermined time, using the Deferred library.

To start we will need to configure our app.yaml to use the Deferred library and the aforementioned APIs:

application: deferred-example
version: 1
runtime: python27
api_version: 1
threadsafe: true

libraries:
- name: jinja2
version: latest

builtins:
- deferred: on

handlers:
- url: /
script: main.app

Next we create a python file named main.py, in this file we will program everything we want our app to do.

First we add our import statement to extend app engines functionality, we do so by adding:

import jinja2
import logging
import os
import webapp2
from google.appengine.api import mail
from google.appengine.ext import deferred

Next we instantiate Jinja2 by writing the following:

jinja_environment = jinja2.Environment(
loader = jinja2.FileSystemLoader(os.path.dirname(__file__)))

app = webapp2.WSGIApplication(
[('/', IndexPage),])

We then set some constants to declare what we can to the email to contain and when to send the email:

# Details for sending the deferred email
SENDER = "Test Sender"
SUBJECT = "Hello World"
BODY = "This message was sent 10 minutes after the user entered his/her email address"

# Time deferred before sending the email in seconds
EMAIL_DELAY = 600

We then create a handler class to manage the page request and POST of the user email address:

class IndexPage(webapp2.RequestHandler):
""" GET method that serves the index page. """

def get(self):
template_values = {}
template = jinja_environment.get_template("index.html")
self.response.out.write(template.render(template_values))

def post(self):
""" POST method for accepting email sign ups. """
email = self.request.get("email")
email_delay(email=email)

Next we create a function to place the user provided email with our constants decalared earlier:

def send_email(email):
""" Sends a delayed email to the person who has entered their address.

Args:
  email: The email to send to.
"""
if not mail.is_email_valid(email): # only checks if non-empty
return False
try:
mail.email_delay(SENDER, email, SUBJECT, BODY)
except Exception, e:
logging.error("Unable to send email to {0}: {1}".format(
email, str(e)))
return False

We then create a function to send the email at a later time:

def email_delay(email):
""" Sends a delayed email to the user provided address. """
deferred.defer(send_email, email, _countdown=EMAIL_DELAY)

Now that we have the core of our application complete we can create the HTML input to be served by webapp2. Here we create a file named index.html and place the HTML used to POST the user provided email address:

<form action="/" method="POST"> <label for="email">Email Address:</label> <input id="email" name="email" required="" type="email"> <input class="btn" type="submit"> </form>

That wraps up today’s tutorial on the Deferred library and the Task Queue API, the entire app can be viewed and cloned on Github.

Topics: Industry News, Best Practices

Subscribe to Email Updates