2
0
mirror of https://github.com/hibiken/asynq.git synced 2024-09-20 11:05:58 +08:00
asynq/client.go

125 lines
2.9 KiB
Go
Raw Normal View History

2020-01-03 10:13:16 +08:00
// Copyright 2020 Kentaro Hibino. All rights reserved.
// Use of this source code is governed by a MIT license
// that can be found in the LICENSE file.
package asynq
import (
"strings"
"time"
2019-12-22 23:15:45 +08:00
"github.com/hibiken/asynq/internal/base"
2019-12-04 13:01:26 +08:00
"github.com/hibiken/asynq/internal/rdb"
"github.com/rs/xid"
)
2019-12-07 14:00:09 +08:00
// A Client is responsible for scheduling tasks.
//
2019-12-09 22:52:43 +08:00
// A Client is used to register tasks that should be processed
2019-12-07 14:00:09 +08:00
// immediately or some time in the future.
//
// Clients are safe for concurrent use by multiple goroutines.
type Client struct {
2019-12-04 13:01:26 +08:00
rdb *rdb.RDB
}
2020-01-17 11:50:45 +08:00
// NewClient and returns a new Client given a redis connection option.
func NewClient(r RedisConnOpt) *Client {
rdb := rdb.NewRDB(createRedisClient(r))
return &Client{rdb}
}
2020-01-17 11:50:45 +08:00
// Option specifies the task processing behavior.
type Option interface{}
// Internal option representations.
type (
2020-02-12 13:53:59 +08:00
retryOption int
queueOption string
timeoutOption time.Duration
)
// MaxRetry returns an option to specify the max number of times
2020-01-06 23:21:14 +08:00
// the task will be retried.
//
// Negative retry count is treated as zero retry.
func MaxRetry(n int) Option {
if n < 0 {
n = 0
}
return retryOption(n)
}
2020-01-17 11:50:45 +08:00
// Queue returns an option to specify the queue to enqueue the task into.
//
// Queue name is case-insensitive and the lowercased version is used.
2020-01-06 23:21:14 +08:00
func Queue(name string) Option {
return queueOption(strings.ToLower(name))
}
2020-02-12 13:53:59 +08:00
// Timeout returns an option to specify how long a task may run.
//
// Zero duration means no limit.
func Timeout(d time.Duration) Option {
return timeoutOption(d)
}
type option struct {
2020-02-12 13:53:59 +08:00
retry int
queue string
timeout time.Duration
}
func composeOptions(opts ...Option) option {
res := option{
2020-02-12 13:53:59 +08:00
retry: defaultMaxRetry,
queue: base.DefaultQueueName,
timeout: 0,
}
for _, opt := range opts {
switch opt := opt.(type) {
case retryOption:
res.retry = int(opt)
case queueOption:
res.queue = string(opt)
2020-02-12 13:53:59 +08:00
case timeoutOption:
res.timeout = time.Duration(opt)
default:
// ignore unexpected option
}
}
return res
}
const (
// Max retry count by default
defaultMaxRetry = 25
)
// Schedule registers a task to be processed at the specified time.
2019-12-07 14:00:09 +08:00
//
// Schedule returns nil if the task is registered successfully,
2020-01-17 11:50:45 +08:00
// otherwise returns a non-nil error.
2019-12-22 02:02:03 +08:00
//
// opts specifies the behavior of task processing. If there are conflicting
2020-01-17 11:50:45 +08:00
// Option values the last one overrides others.
func (c *Client) Schedule(task *Task, processAt time.Time, opts ...Option) error {
opt := composeOptions(opts...)
2019-12-22 23:15:45 +08:00
msg := &base.TaskMessage{
ID: xid.New(),
Type: task.Type,
Payload: task.Payload.data,
Queue: opt.queue,
Retry: opt.retry,
2020-02-12 13:53:59 +08:00
Timeout: opt.timeout.String(),
}
2019-11-27 23:16:16 +08:00
return c.enqueue(msg, processAt)
}
2019-12-22 23:15:45 +08:00
func (c *Client) enqueue(msg *base.TaskMessage, processAt time.Time) error {
2019-11-27 23:16:16 +08:00
if time.Now().After(processAt) {
2019-12-04 13:01:26 +08:00
return c.rdb.Enqueue(msg)
}
return c.rdb.Schedule(msg, processAt)
}