-
-
Notifications
You must be signed in to change notification settings - Fork 722
Task Timeout and Cancelation
In this page, I'll explain how to set timeout or deadline for a task, and how to handle cancelations.
When you enqueue a task with Client
, you can specify Timeout
or Deadline
as an option, so that if the task doesn't get processed within that timeout or before that deadline, Server can abandon the work to reclaim resources for other tasks.
These options will set the timeout, deadline value of the context.Context
, which gets passed as the first argument to your Handler.
*Note: The timeout is relative to the time that Handler started to process the task.
For example, if you have a task that should be completed within 30 seconds, you can set the timeout duration to be 30*time.Second
.
c := asynq.NewClient(asynq.RedisClientOpt{Addr: ":6379"})
err := c.Enqueue(task, asynq.Timeout(30 * time.Second))
If you have a task that should be completed before certain time, you can set the deadline for that task.
For example, if you have a task that should be completed before 2020-12-25
, you can pass that as Deadline
option.
xmas := time.Date(2020, time.December, 12, 25, 0, 0, 0, time.UTC)
err := c.Enqueue(task, asynq.Deadline(xmas))
Now that we've created tasks with Timeout
and Deadline
option, we have to respect that value by reading Done
channel in the context.
The first argument passed to the Handler
is context.Context
. You should write your Handler in such a way that it abandons the work if the cancelation signal is received from the context.
func myHandler(ctx context.Context, task *asynq.Task) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
c := make(chan error, 1)
go func() {
select {
case c <- doWork(task):
case <-ctx.Done():
// if cancel, Goroutine exit
return
}
}()
select {
case <-ctx.Done():
// cancelation signal received, abandon this work.
return ctx.Err()
case res := <-c:
return res
}
}
asynq
CLI has the cancel
command which takes the ID of the task to cancel active tasks.
You can inspect currently active tasks with workers
command and grab the ID to cancel a task.
asynq task ls --queue=myqueue --state=active
asynq task cancel [task_id]