mirror of
https://github.com/hibiken/asynq.git
synced 2024-12-26 07:42:17 +08:00
Change package APIs
This commit is contained in:
parent
f4d59bece7
commit
d2d0d1fde5
54
asynq.go
54
asynq.go
@ -1,11 +1,19 @@
|
|||||||
package asynq
|
package asynq
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODOs:
|
||||||
|
- [P0] Task error handling
|
||||||
|
- [P0] Retry
|
||||||
|
- [P0] Dead task (retry exausted)
|
||||||
|
- [P0] Shutdown all workers gracefully when killed
|
||||||
|
- [P1] Add Support for multiple queues
|
||||||
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v7"
|
"github.com/go-redis/redis/v7"
|
||||||
@ -26,8 +34,12 @@ type Client struct {
|
|||||||
|
|
||||||
// Task represents a task to be performed.
|
// Task represents a task to be performed.
|
||||||
type Task struct {
|
type Task struct {
|
||||||
Handler string
|
// Type indicates the kind of the task to be performed.
|
||||||
Args []interface{}
|
Type string
|
||||||
|
|
||||||
|
// Payload is an arbitrary data needed for task execution.
|
||||||
|
// The value has to be serializable.
|
||||||
|
Payload map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type delayedTask struct {
|
type delayedTask struct {
|
||||||
@ -48,8 +60,13 @@ func NewClient(opt *RedisOpt) *Client {
|
|||||||
return &Client{rdb: rdb}
|
return &Client{rdb: rdb}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enqueue pushes a given task to the specified queue.
|
// Process enqueues the task to be performed at a given time.
|
||||||
func (c *Client) Enqueue(queue string, task *Task, executeAt time.Time) error {
|
func (c *Client) Process(task *Task, executeAt time.Time) error {
|
||||||
|
return c.enqueue("default", task, executeAt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// enqueue pushes a given task to the specified queue.
|
||||||
|
func (c *Client) enqueue(queue string, task *Task, executeAt time.Time) error {
|
||||||
if time.Now().After(executeAt) {
|
if time.Now().After(executeAt) {
|
||||||
return push(c.rdb, queue, task)
|
return push(c.rdb, queue, task)
|
||||||
}
|
}
|
||||||
@ -74,9 +91,6 @@ type Workers struct {
|
|||||||
// poolTokens is a counting semaphore to ensure the number of active workers
|
// poolTokens is a counting semaphore to ensure the number of active workers
|
||||||
// does not exceed the limit.
|
// does not exceed the limit.
|
||||||
poolTokens chan struct{}
|
poolTokens chan struct{}
|
||||||
|
|
||||||
// handlers maps queue name to a handler for that queue's messages.
|
|
||||||
handlers map[string]func(msg string)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWorkers creates and returns a new Workers.
|
// NewWorkers creates and returns a new Workers.
|
||||||
@ -85,17 +99,14 @@ func NewWorkers(poolSize int, opt *RedisOpt) *Workers {
|
|||||||
return &Workers{
|
return &Workers{
|
||||||
rdb: rdb,
|
rdb: rdb,
|
||||||
poolTokens: make(chan struct{}, poolSize),
|
poolTokens: make(chan struct{}, poolSize),
|
||||||
handlers: make(map[string]func(string)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle registers a handler function for a given queue.
|
// TaskHandler handles a given task and report any error.
|
||||||
func (w *Workers) Handle(q string, fn func(msg string)) {
|
type TaskHandler func(*Task) error
|
||||||
w.handlers[q] = fn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run starts the workers and scheduler.
|
// Run starts the workers and scheduler with a given handler.
|
||||||
func (w *Workers) Run() {
|
func (w *Workers) Run(handler TaskHandler) {
|
||||||
go w.pollScheduledTasks()
|
go w.pollScheduledTasks()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@ -111,16 +122,17 @@ func (w *Workers) Run() {
|
|||||||
|
|
||||||
q, msg := res[0], res[1]
|
q, msg := res[0], res[1]
|
||||||
fmt.Printf("perform task %v from %s\n", msg, q)
|
fmt.Printf("perform task %v from %s\n", msg, q)
|
||||||
handler, ok := w.handlers[strings.TrimPrefix(q, queuePrefix)]
|
var task Task
|
||||||
if !ok {
|
err = json.Unmarshal([]byte(msg), &task)
|
||||||
log.Printf("no handler found for queue %q\n", strings.TrimPrefix(q, queuePrefix))
|
if err != nil {
|
||||||
|
log.Printf("[Servere Error] could not parse json encoded message %s: %v", msg, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
w.poolTokens <- struct{}{} // acquire a token
|
w.poolTokens <- struct{}{} // acquire a token
|
||||||
go func(msg string) {
|
go func(task *Task) {
|
||||||
handler(msg)
|
handler(task)
|
||||||
<-w.poolTokens
|
<-w.poolTokens
|
||||||
}(msg)
|
}(&task)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user