-
Notifications
You must be signed in to change notification settings - Fork 64
creating push tasks
This page describes how to create tasks and place them in push queues. When you want to process a task, you must create a new task object and place it on a queue. You can explicitly specify the service and handler that process the task, and optionally pass task-specific data along to the handler. You can also fine-tune the configuration for the task, like scheduling a time in the future when it should be executed or limiting the number of times you want the task to be retried if it fails.
To create and enqueue a task, get a Queue using the QueueFactory, and call
its add() method. You can get a named queue specified in the queue.xml file
using the getQueue() method of the factory, or you can get the default queue
using getDefaultQueue(). You can call the Queue's add() method with a
TaskOptions instance produced by TaskOptions.Builder, or you can call
it with no arguments to create a task with the default options for the queue.
View Enqueue.java on GitHub (region:
import)
View Enqueue.java on GitHub (region:
addQueue)
To create and enqueue a task, create a PushTask object and call its
add() method. You can add to a queue specified in queue.yaml by supplying a
queue name argument to add(). Alternatively, calling add() with no arguments
will add the task to the default queue.
You can also add tasks in bulk to a queue using PushQueue. In the
following example, two PushTask objects are added to a
PushQueue using the addTasks() method.
The following code sample shows how to add a single task:
The following code sample shows how to add multiple tasks at once:
When you use PushTask and PushQueue, include these statements at the top of
your PHP file:
To create and enqueue a task, call the taskqueue.Add function.
import("google.golang.org/appengine/v2/taskqueue")
To create and enqueue a task, call the
taskqueue.add()
function.
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.
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 forms 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:
-
Declare the target when you construct the task.
You can set the target explicitly when creating the task by setting the `Host` header using `TaskOptions`: taskOptions.header("Host", versionHostname) You can set the target explicitly when creating the task by using the header parameter in the `$options` array when you construct the [PushTask](https://googlecloudplatform.github.io/appengine-php-sdk/2.1.0/Google/AppEngine/Api/TaskQueue/PushTask.html) object:
<code>$task = new PushTask(
'/worker',
[],
['header' => "Host: versionHostname"]);</code>
You can set the target explicitly when creating the [Task](https://cloud.google.com/appengine/docs/standard/go/reference/services/bundled/latest/taskqueue) object by setting
the `Host` header:
You can set the target explicitly using the `target` parameter in the [`taskqueue.add()`](https://cloud.google.com/appengine/docs/standard/python3/reference/services/bundled/google/appengine/api/taskqueue/add)
function. See the example above.
-
Include a
targetdirective when you define a queue in thequeue.yaml, as in the definition ofqueue-blue. All tasks added to a queue with atargetwill 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.
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 method specified in the task 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.
You can pass data to the handler as query parameters in the task's URL, but only
if the method specified in the task is GET or PULL.
TaskOptions.Builder constructor has methods to add data as the payload
of the HTTP request, and as parameters, which are added to the URL as query
parameters.
params : Do not specify params if you are using the POST method along with a
payload, or if you are using the GET method and you've included a url with
query parameters.
The PushTask constructor 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.
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.
You can also use any of the following fields to add data to a task:
-
payload, which delivers task data in the body of the HTTP request. params
Note: Don't specify params if you are using the HTTP POST method along with a
payload, or if you are using the HTTP GET method and you've included a URL
with query parameters.
These three calls are equivalent:
taskqueue.add(method=GET, url='/update-counter?key=blue', target='worker')
taskqueue.add(url='/update-counter', params={'key': 'blue'}, target='worker')
taskqueue.add(url='/update-counter', payload="{'key': 'blue'}", target='worker')
When you create a new task, App Engine assigns the task a unique name by
default. However, you can assign your own name to a task by using the name
parameter. An advantage of assigning your own task names is that named tasks are
de-duplicated, which means you can use task names to
guarantee that a
task is only added once. De-duplication continues for 9 days after the task is
completed or deleted.
Note that de-duplication logic introduces significant performance overhead, resulting in increased latencies and potentially increased error rates associated with named tasks. These costs can be magnified significantly if task names are sequential, such as with timestamps. So, if you assign your own names, we recommend using a well-distributed prefix for task names, such as a hash of the contents.
If you assign your own names to tasks, note that the maximum name length is 500 characters, and the name can contain uppercase and lowercase letters, numbers underscores, and hyphens.
taskqueue.add(url='/url/path', name='first-try')
By default, the calls that add tasks to queues are synchronous. For most scenarios, synchronous calls work fine. Adding a task to a queue is usually a fast operation. There are a small percentage of add task operations that can take significantly longer, but the median time to add a task is less than 5 ms.
Add task operations to different queues cannot be batched, so the Task Queue API also provides asynchronous calls that give you the ability to add these tasks in parallel, further minimizing this latency. This is useful if you are building an extremely latency sensitive application that needs to perform several add task operations to different queues at the same time.
If you want to make asynchronous calls to a task queue, use the asynchronous
methods provided by the
Queue
class. Call get on the returned Future to force the request to complete.
When asynchronously adding tasks in a transaction, you should call get() on
the Future before committing the transaction to ensure that the request has
finished
Queue
class and an
RPC
object. Call get_result() on the returned RPC object to force the request to
complete. When asynchronously adding tasks in a transaction, you should call
get_result() on the RPC object before committing the transaction to ensure
that the request has finished
You can enqueue a task as part of a 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 transaction
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 Datastore transaction:
import (
"net/url"
"golang.org/x/net/context"
"google.golang.org/appengine/v2"
"google.golang.org/appengine/v2/datastore"
"google.golang.org/appengine/v2/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
}
// ...
}DeferredTasks
delayed package
deferred task library 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 Java SDK includes an interface called DeferredTask. This interface lets you define a task as a single method. This interface uses Java serialization to package a unit of work into a Task Queue. A simple return from that method is considered success. Throwing any exception from that method is considered a failure.
View DeferSampleServlet.java on GitHub (region:
defer)
Warning: While the DeferredTask API is a convenient way to handle serialization, you have to carefully control the serialization compatibility of objects passed into payload methods. Careful control is necessary because unprocessed objects remain in the task queue, even after the application code is updated. Tasks based on outdated application code will not deserialize properly when the task is decoded with new revisions of the application.
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:
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
delay.
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 Python SDK includes a library
(google.appengine.ext.deferred) exposing a simple function that allows you to
bypass all the work of setting up dedicated task handlers and serializing and
deserializing your parameters.
To use this library, you need to add the deferred builtin to app.yaml. For
more information, see the Built-in Handlers
section of the app.yaml reference.
To use the deferred library, simply pass the function and its arguments to
deferred.defer():
The deferred library packages your function call and its arguments, then adds
it to the task queue. When the task is executed, the deferred library executes
do_something_expensive("Hello, world!", 42, True).
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 API.
- Learn how to create task handlers.