タスクのタイムアウト

このページでは、タスクのタイムアウトや締め切りの設定方法、またキャンセル操作の処理方法について紹介します。

Clientを使用してタスクをキューに入れる際、TimeoutまたはDeadlineをオプションとして指定することができます。これにより、サーバーはタスクがタイムアウトや締め切り前に処理されない場合には、そのタスクを諦めて他のタスクのためにリソースを回収することができます。 これらのオプションはcontext.Contextのタイムアウトや締め切りを設定し、それをハンドラーの最初のパラメータとして渡します。

*注:タイムアウトはハンドラーがタスクの処理を開始した時点からの相対的な時間です。

例えば、30秒以内に完了する必要があるタスクがある場合は、タイムアウトを30*time.Secondに設定できます。

c := asynq.NewClient(asynq.RedisClientOpt{Addr: ":6379"})

err := c.Enqueue(task, asynq.Timeout(30 * time.Second))

特定の時間までに完了する必要があるタスクがある場合は、そのタスクの締め切りを設定します。 例えば、2020年12月25日までに完了する必要があるタスクがある場合は、Deadlineオプションとして渡すことができます。

xmas := time.Date(2020, time.December, 25, 0, 0, 0, 0, time.UTC)
err := c.Enqueue(task, asynq.Deadline(xmas))

ハンドラー内のタスクコンテキスト

TimeoutDeadlineオプションを使用してタスクを作成したら、コンテキスト内のDoneチャンネルを読むことで、その値を尊重する必要があります。

Handlerに渡される最初のパラメータはcontext.Contextです。コンテキストからキャンセルシグナルを受け取った場合に作業を中止するようにハンドラーを記述する必要があります。

func myHandler(ctx context.Context, task *asynq.Task) error {
    c := make(chan error, 1)
    go func() {
        c <- doWork(task)
    }()
    select {
    case <-ctx.Done():
        // キャンセルシグナルを受信しました。この作業を中止します。
        return ctx.Err()
    case res := <-c:
        return res
    }   
}

CLIを使用したタスクのキャンセル

asynq CLIには、アクティブなタスクのIDをキャンセルできるcancelコマンドがあります。 現在アクティブなタスクを確認し、キャンセルするタスクのIDを取得するためにworkersコマンドを使用することができます。

asynq task ls --queue=myqueue --state=active
asynq task cancel [task_id]