Google AppEngine: Task Queues API
com.google.appengine.api.taskqueue
Queue Configuration
1. Push Queues (default):
Push queue will process tasks based on the processing rate configured in the queue definition (see below). App Engine automatically manages the lifetime of these queues (creation, deletion, etc) and adjusts the processing capacity to match your configuration and processing volume. These can only be used within App Engine (internal to your app).
2. Pull Queues:
Allow a task consumer to lease tasks at a specific time within a specific timeframe. They are accessible internally as well as externally through the Task Queue REST API. In this scenarion, however, GAE does not manage the lifecycle and processing rate of queues automatically, it is up to the developer to do it. A backend also has access to these queues.
Tasks
Task within a Transaction
Tasks can be enqueued as part of a datastore transaction. Insertion (not execution) will be guaranteed if the transaction was committed successfully. The only caveat is that Transactional tasks cannot have user-defined names and there is a maximum of 5 insertions into task queues in a single transaction.
Configuration
Here are some of things you are allowed to configure (the documentation is more extensive):
• bucket-size: how fast the queue is processed when many tasks are in the queue and the rate is high (push only). (Warning: Development server ignores this value)
• max-concurrent-requests: maximum number of tasks that can be executed at any \ given time in the specified queue (push only).
• mode: whether it’s push or pull.
• name: queue name
• target: target a task to a specfic backend or application version.
<queue-entries> <!--Set the number of max concurrent requests to 10--> <queue> <name>optimize-queue</name> <rate>20/s</rate> <bucket-size>40</bucket-size> <max-concurrent-requests>10</max-concurrent-requests> </queue> </queue-entries>
Sample Code
public class TaskQInfo extends HttpServlet { private static volatile int TASK_COUNTER = 0; // Executed by user menu click public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { // Build a task using the TaskOptions Builder pattern from ** above Queue queue = QueueFactory.getDefaultQueue(); queue.add(withUrl("/taskq_demo").method(TaskOptions.Method.POST)); resp.getWriter().println("Task have been added to default queue..."); resp.getWriter().println("Refresh this page to add another count task"); } // Executed by TaskQueue @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // This is the body of the task for(int i = 0; i < 1000; i++) { log.info("Processing: " + req.getHeader("X-AppEngine-TaskName") + "-" + TASK_COUNTER++); try { // Sleep for a second (if the rate is set to 1/s this will allow at // most 1 more task to be processed) Thread.sleep(1000); } catch (InterruptedException e) { // ignore} } } }
Task queues allow you to achieve some level of concurrency in your application by invoking background processes on demand. For very lengthy tasks, you might want to take a look at App Engine backends, which are basically special App Engine instances with no request time limit.
Reference: Google AppEngine: Task Queues API from our JCG partner Luis Atencio at the Reflective Thought blog.