push タスクの作成

このページでは、タスクを作成して push キューに配置する方法を説明します。タスクを処理する場合は、新しいタスク オブジェクトを作成してキューに配置する必要があります。タスクを処理するサービスとハンドラを明示的に指定し、必要に応じてタスク固有のデータをハンドラに渡すこともできます。また、タスクを実行するタイミングをスケジューリングしたり、失敗した場合にタスクを再試行する回数を制限したりするなど、タスクの構成を微調整することもできます。

新しいタスクを作成する

タスクを作成してキューに追加するには、taskqueue.Add 関数を呼び出します。

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

ワーカー サービスを指定する

タスクがキューから取り出される(ポップ)と、タスクはタスクキュー サービスによってワーカー サービスに送信されます。どのタスクにもターゲットと url があり、どのサービスとハンドラがそのタスクを実行するかがこれらによって決まります。

target

ターゲットは、どのサービスがタスク実行の HTTP リクエストを受け取るかを指定します。これは文字列であり、サービス / バージョン / インスタンスを正規形式のいずれかで指定します。最もよく使用される形式は次のとおりです。

    service
    version.service
    instance.version.service

ターゲット文字列の前には、アプリのドメイン名が付加されます。タスクのターゲットを設定するには、次の 3 つの方法があります。

  • タスクを作成するときにターゲットを宣言します。Task オブジェクトの作成時にターゲットを明示的に設定するには、Host ヘッダーを設定します。

    h := http.Header{}
    h.Add("Host", "versionHostname")
    task := taskqueue.Task{
    	Header: h,
    }

  • queue.yaml でキューを定義するときに、target ディレクティブを指定します(queue-blue定義をご覧ください)。target が指定されているキューに追加されるタスクはすべて、そのターゲットを使用します。タスクの作成時に別のターゲットが割り当てられていても無視されます。

  • 上記の 2 つの方法のいずれかでターゲットが指定されていない場合、タスクをキューに追加したサービスのバージョンが、そのタスクのターゲットになります。このようにしてデフォルトのサービスとバージョンのタスクがキューに追加された場合、タスクの実行前にデフォルトのバージョンが変更されると、タスクは変更後のデフォルトのバージョンで実行されます。

url

url に基づいて、ターゲット サービスのハンドラの 1 つが選択され、そのハンドラによってタスクが実行されます。

url は、ターゲット サービス内のハンドラ URL パターンの 1 つに一致する必要があります。タスクに指定されたメソッドが GET または PULL である場合は、url にクエリ パラメータを含めることができます。url が指定されていない場合は、デフォルトの URL /_ah/queue/[QUEUE_NAME] が使用されます。ここで [QUEUE_NAME] はタスクのキューの名前です。

データをハンドラに渡す

データをハンドラに渡す場合、タスクの URL 内のクエリ パラメータとして渡す方法がありますが、この方法が可能なのはタスクで指定されているメソッドが GET または PULL の場合のみです。

NewPOSTTask 関数には query_data の位置引数が含まれています。データは通常、Key-Value ペアの辞書です。タスクのメソッドが POST または PUT の場合、データは HTTP リクエストのペイロードに追加されます。メソッドが GET の場合は、URL にクエリ パラメータとして追加されます。

タスクに名前を付ける

新しいタスクを作成すると、デフォルトでは App Engine によってタスクに一意の名前が割り当てられます。ただし、name パラメータを使用すると、タスクに独自の名前を割り当てることができます。独自のタスク名を割り当てることの利点は、名前付きのタスクでは重複が除外されることです。つまり、タスク名を使用すると、タスクが 1 回のみ追加されることを保証できます。重複の除外は、タスクが完了するか、削除されてから 9 日間続きます。

重複の除外ロジックではパフォーマンスのオーバーヘッドが大幅に増加するため、レイテンシが増加し、場合によっては名前付きタスクに伴うエラー率が高まるので注意してください。このようなコストは、タイムスタンプのように連続したタスク名が付けられている場合、大幅に増大する可能性があります。そのため、独自の名前を割り当てる場合は、コンテンツのハッシュなどの適度に分散された接頭辞をタスク名に使用することをおすすめします。

独自の名前をタスクに割り当てる場合、名前の最大長が 500 文字で、名前には英字の大文字と小文字、数字、アンダースコア、ハイフンを使用できることに注意してください。

Cloud Datastore トランザクションの中でタスクをキューに追加する

タスクをキューに追加する処理を、Cloud Datastore トランザクションの一部として行うことができます。このようにすると、タスクがキューに追加される(かつ、キューへの追加が保証される)のは、トランザクションが正常に commit された場合のみとなります。トランザクションの中で追加されたタスクは、そのトランザクションの一部と見なされ、同じレベルの分離と整合性を持つことになります。

1 つのトランザクションの中でタスクキューに挿入できるトランザクション タスクは 5 個までです。トランザクション タスクの名前をユーザーが指定することはできません。

次のコードサンプルでは、Cloud Datastore トランザクションの一部としてトランザクション タスクを push キューに追加する方法を示します。

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
	}
	// ...
}

ワーカー サービスの代わりに遅延パッケージを使用する

上記のセクションで説明したように、実行するタスクごとに別個にハンドラを設定すると、タスクの複雑な引数のシリアル化 / シリアル化解除と同様、煩雑になる場合があります。特に、キューで実行するタスクが小さく、多種多様で数も多い場合には、厄介です。Go SDK に含まれるパッケージ(appengine/delay)を使用すると、単純な API をエクスポーズするだけで、専用のタスクハンドラの設定やパラメータのシリアル化 / シリアル化解除の作業をすべて回避できます。

delay パッケージを使用する手順は次のとおりです。

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)

delay パッケージは関数の呼び出しとその引数をシリアル化して、タスクキューに追加します。タスクの実行時に、delay パッケージで関数が実行されます。

delay パッケージの使用方法の詳細については、該当のドキュメントをご覧ください。

マルチテナント アプリケーションでタスクを扱う

デフォルトでは、push キューについては、タスクの作成時に名前空間マネージャで設定されていた現在の名前空間が使用されます。アプリケーションでマルチテナントを使用する場合は、名前空間 Go API をご覧ください。

次のステップ

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

Go の App Engine スタンダード環境