mirror of
https://github.com/hibiken/asynq.git
synced 2025-04-21 16:20:18 +08:00
Change dequeue method to use lua script
This commit is contained in:
parent
5c42bdc4c4
commit
6de80f9f04
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/go-redis/redis/v7"
|
"github.com/go-redis/redis/v7"
|
||||||
"github.com/hibiken/asynq/internal/base"
|
"github.com/hibiken/asynq/internal/base"
|
||||||
|
"github.com/spf13/cast"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -46,20 +47,16 @@ func (r *RDB) Enqueue(msg *base.TaskMessage) error {
|
|||||||
return r.client.LPush(qname, string(bytes)).Err()
|
return r.client.LPush(qname, string(bytes)).Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dequeue blocks until there is a task available to be processed,
|
// Dequeue queries the queues in the given order and returns a task message if
|
||||||
// once a task is available, it adds the task to "in progress" queue
|
// one is found. If all queues are empty it returns ErrNoProcessableTask error.
|
||||||
// and returns the task. If there are no tasks for the entire timeout
|
|
||||||
// duration, it returns ErrDequeueTimeout.
|
|
||||||
func (r *RDB) Dequeue(queues ...string) (*base.TaskMessage, error) {
|
func (r *RDB) Dequeue(queues ...string) (*base.TaskMessage, error) {
|
||||||
data, err := r.dequeue(queues...)
|
data, err := r.dequeue(queues...)
|
||||||
if err == redis.Nil {
|
if err == redis.Nil {
|
||||||
// all queues are empty // TODO(hibiken): Rename this sentinel error
|
|
||||||
return nil, ErrNoProcessableTask
|
return nil, ErrNoProcessableTask
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var msg base.TaskMessage
|
var msg base.TaskMessage
|
||||||
err = json.Unmarshal([]byte(data), &msg)
|
err = json.Unmarshal([]byte(data), &msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -69,16 +66,25 @@ func (r *RDB) Dequeue(queues ...string) (*base.TaskMessage, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *RDB) dequeue(queues ...string) (data string, err error) {
|
func (r *RDB) dequeue(queues ...string) (data string, err error) {
|
||||||
|
var args []interface{}
|
||||||
for _, qname := range queues {
|
for _, qname := range queues {
|
||||||
data, err = r.client.RPopLPush(qname, base.InProgressQueue).Result()
|
args = append(args, qname)
|
||||||
if err == nil {
|
|
||||||
return data, nil
|
|
||||||
}
|
}
|
||||||
if err != redis.Nil {
|
script := redis.NewScript(`
|
||||||
|
local res
|
||||||
|
for _, qname in ipairs(ARGV) do
|
||||||
|
res = redis.call("RPOPLPUSH", qname, KEYS[1])
|
||||||
|
if res then
|
||||||
|
return res
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return res
|
||||||
|
`)
|
||||||
|
res, err := script.Run(r.client, []string{base.InProgressQueue}, args...).Result()
|
||||||
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
return cast.ToStringE(res)
|
||||||
return data, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Done removes the task from in-progress queue to mark the task as done.
|
// Done removes the task from in-progress queue to mark the task as done.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user