Creating Tasks

This page describes how to create tasks and place them in push queues. When you want to run a task, you must create a new task and place it on a queue. You can explicitly specify the service and handler that processes the task, and optionally pass task-specific data along to the handler.

Creating a new task

To create and enqueue a task, call the taskqueue.Add function.

import("google.golang.org/appengine/taskqueue")

Specifying the worker service

When a task is popped off its queue, the Task Queue service sends it on to a worker service. Every task has a target and a url, which determine what service and handler will ultimately perform the task.

target

The target specifies the service that will receive the HTTP request to perform the task. It is a string that specifies a service/version/instance in any one of the canonical forms. The most often-used ones are:

service
version.service
instance.version.service

The target string is prepended to the domain name of your app. There are three ways to set the target for a task:

  • Explicity declare the target when you construct the task.

  • Include a target directive when you define a queue in the queue.yaml, as in the definition of queue-blue above. All tasks added to a queue with a target will use that target, even if a different target was assigned to the task at construction time.

  • If no target is specified according to either of the previous two methods, then the task's target is the version of the service that enqueues it. Note that if you enqueue a task from the default service and version in this manner, and the default version changes before the task executes, it will run in the new default version.

url

The url selects one of the handlers in the target service, which will perform the task.

The url should match one of the handler URL patterns in the target service. The url can include query parameters if the tasks's method is GET or PULL. If no url is specified the default URL /_ah/queue/[QUEUE_NAME] is used, where [QUEUE_NAME] is the name of the task's queue.

Passing data to the handler

You can pass data to the handler as query parameters in the task's URL—but only if you set the task's method to GET or PULL.

The NewPOSTTask function has a positional argument for query_data. The data is usually a dictionary of key-value pairs. If the task's method is POST or PUT, the data is added to the payload of the HTTP request. If the method is GET it is added to the URL as query parameters.

Naming a task

When you create a new task, App Engine assigns the task a unique name by default. You can assign your own name to a task by using the name parameter.

A task name must be unique within a queue. If you try to add another task with the same name to a the queue, the operation will fail. After a task is removed from a queue you can't insert a task with the same name into the queue until 10 days have passed. A task name can contain uppercase and lowercase letters, numbers, underscores, and hyphens. The maximum length for a task name is 500 characters.

Recommended: Let App Engine generate task names automatically.

Enqueuing tasks in Cloud Datastore transactions

You can enqueue a task as part of a Google Cloud Datastore transaction, such that the task is only enqueued—and guaranteed to be enqueued—if the transaction is committed successfully. Tasks added in a transaction are considered to be a part of it and have the same level of isolation and consistency.

An application cannot insert more than five transactional tasks into task queues during a single transaction. Transactional tasks must not have user-specified names.

The following code sample demonstrates how to insert transactional tasks into a push queue as part of a Cloud Datastore transaction:

import (
	"net/url"

	"golang.org/x/net/context"

	"google.golang.org/appengine/datastore"
	"google.golang.org/appengine/taskqueue"
)

func f(ctx context.Context) {
	err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
		t := taskqueue.NewPOSTTask("/worker", url.Values{
		// ...
		})
		// Use the transaction's context when invoking taskqueue.Add.
		_, err := taskqueue.Add(ctx, t, "")
		if err != nil {
			// Handle error
		}
		// ...
		return nil
	}, nil)
	if err != nil {
		// Handle error
	}
	// ...
}

Using the delayed package instead of a worker service

Setting up a handler for each distinct task (as described in the previous sections) can be cumbersome, as can serializing and deserializing complex arguments for the task—particularly if you have many diverse but small tasks that you want to run on the queue. The Go SDK includes a package (appengine/delay) exposing a simple API that allows you to bypass all the work of setting up dedicated task handlers and serializing and deserializing your parameters.

To use the delay package:

var expensiveFunc = delay.Func("some-arbitrary-key", func(ctx context.Context, a string, b int) {
	// do something expensive!
})

// Somewhere else
expensiveFunc.Call(ctx, "Hello, world!", 42)

The delay package serializes your function call and its arguments, then adds it to the task queue. When the task is executed, the delay package executes the function.

For more information about using the delay package, refer to its documentation.

Working with tasks in a multi-tenant application

By default, push queues use the current namespace as set in the namespace manager at the time the task is created. If your application uses multitenancy, see the Namespaces Go API.

What's next

Send feedback about...

App Engine standard environment for Go