简单版:
func (dao *defaultRedisDao) ZAdd(ctx context.Context, key, member string, delayTime float64) error {
z := &redis.Z{
Member: member,
Score: delayTime + float64(time.Now().Unix()),
}
err := dao.cache.ZAdd(ctx, key, z).Err()
if err != nil {
return errors.Wrapf(err, "ZAdd failed key:%s, z:%+v", key, *z)
}
return nil
}
opt := &redis.ZRangeBy{
Min: "0",
Max: cast.ToString(time.Now().Unix()),
Offset: 0,
Count: 1000,
}
batch, err := l.redisDao.ZRangeByScoreWithScores(ctx, robotdao.ZAddKey, opt)
升级版:
git地址:github.com/hibiken/asy…
延时队列
- client端函数
- func NewClient(r RedisConnOpt) *Client
- func NewEmailDeliveryTask(userID int, tmplID string) (*asynq.Task, error)
- func (c *Client) Enqueue(task *Task, opts ...Option) (*TaskInfo, error)
- func (c *Client) EnqueueContext(ctx context.Context, task *Task, opts ...Option) (*TaskInfo, error)
- func (c *Client) schedule(ctx context.Context, msg *base.TaskMessage, t time.Time, uniqueTTL time.Duration) error
- func (r *RDB) Schedule(ctx context.Context, msg *base.TaskMessage, processAt time.Time) error
- func (r *RDB) runScriptWithErrorCode(ctx context.Context, op errors.Op, script *redis.Script, keys []string, args ...interface{}) (int64, error)
- func (s *Scheduler) waitForSignals()
- func (s *Scheduler) Shutdown()
- func (c *Cron) Stop() context.Context
- server端函数
- func NewServer(r RedisConnOpt, cfg Config) *Server
- func NewServeMux() *ServeMux
- func (mux *ServeMux) HandleFunc(pattern string, handler func(context.Context, *Task) error)
- func (mux *ServeMux) Handle(pattern string, handler Handler)
- func (srv *Server) Start(handler Handler) error
- func (f *forwarder) start(wg *sync.WaitGroup)
- func (r *RDB) ForwardIfReady(qnames ...string) error
- func (r *RDB) forwardAll(qname string) (err error)
- func (r *RDB) forward(delayedKey, pendingKey, taskKeyPrefix, groupKeyPrefix string) (int, error)
client相关的lua脚本
keys := []string{
base.TaskKey(msg.Queue, msg.ID),
base.ScheduledKey(msg.Queue),
}
argv := []interface{}{
encoded,
processAt.Unix(),
msg.ID,
}
var scheduleCmd = redis.NewScript(`
if redis.call("EXISTS", KEYS[1]) == 1 then
return 0
end
redis.call("HSET", KEYS[1],
"msg", ARGV[1],
"state", "scheduled")
redis.call("ZADD", KEYS[2], ARGV[2], ARGV[3])
return 1
`)
server相关的lua脚本
local ids = redis.call("ZRANGEBYSCORE", KEYS[1], "-inf", ARGV[1], "LIMIT", 0, 100)
for _, id in ipairs(ids) do
local taskKey = ARGV[2] .. id
local group = redis.call("HGET", taskKey, "group")
if group and group ~= '' then
redis.call("ZADD", ARGV[4] .. group, ARGV[1], id)
redis.call("ZREM", KEYS[1], id)
redis.call("HSET", taskKey,
"state", "aggregating")
else
redis.call("LPUSH", KEYS[2], id)
redis.call("ZREM", KEYS[1], id)
redis.call("HSET", taskKey,
"state", "pending",
"pending_since", ARGV[3])
end
end
return table.getn(ids)`)
keys := []string{
base.PendingKey(qname),
base.PausedKey(qname),
base.ActiveKey(qname),
base.LeaseKey(qname),
}
var dequeueCmd = redis.NewScript(`
if redis.call("EXISTS", KEYS[2]) == 0 then
local id = redis.call("RPOPLPUSH", KEYS[1], KEYS[3])
if id then
local key = ARGV[2] .. id
redis.call("HSET", key, "state", "active")
redis.call("HDEL", key, "pending_since")
redis.call("ZADD", KEYS[4], ARGV[1], id)
return redis.call("HGET", key, "msg")
end
end
return nil`)