2
0
mirror of https://github.com/hibiken/asynq.git synced 2025-10-02 04:52:01 +08:00

Add Inspector type

This commit is contained in:
Ken Hibino
2020-07-13 06:29:41 -07:00
parent 9bd3d8e19e
commit a28f61f313
20 changed files with 2830 additions and 931 deletions

View File

@@ -8,15 +8,14 @@ import (
"fmt"
"os"
"github.com/go-redis/redis/v7"
"github.com/hibiken/asynq/internal/rdb"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// delCmd represents the del command
var delCmd = &cobra.Command{
Use: "del [task id]",
Use: "del [task key]",
Short: "Deletes a task given an identifier",
Long: `Del (asynq del) will delete a task given an identifier.
@@ -44,27 +43,12 @@ func init() {
}
func del(cmd *cobra.Command, args []string) {
id, score, qtype, err := parseQueryID(args[0])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
r := rdb.NewRDB(redis.NewClient(&redis.Options{
i := asynq.NewInspector(asynq.RedisClientOpt{
Addr: viper.GetString("uri"),
DB: viper.GetInt("db"),
Password: viper.GetString("password"),
}))
switch qtype {
case "s":
err = r.DeleteScheduledTask(id, score)
case "r":
err = r.DeleteRetryTask(id, score)
case "d":
err = r.DeleteDeadTask(id, score)
default:
fmt.Println("invalid argument")
os.Exit(1)
}
})
err := i.DeleteTaskByKey(args[0])
if err != nil {
fmt.Println(err)
os.Exit(1)

View File

@@ -8,8 +8,7 @@ import (
"fmt"
"os"
"github.com/go-redis/redis/v7"
"github.com/hibiken/asynq/internal/rdb"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@@ -45,20 +44,22 @@ func init() {
}
func delall(cmd *cobra.Command, args []string) {
c := redis.NewClient(&redis.Options{
i := asynq.NewInspector(asynq.RedisClientOpt{
Addr: viper.GetString("uri"),
DB: viper.GetInt("db"),
Password: viper.GetString("password"),
})
r := rdb.NewRDB(c)
var err error
var (
n int
err error
)
switch args[0] {
case "scheduled":
err = r.DeleteAllScheduledTasks()
n, err = i.DeleteAllScheduledTasks()
case "retry":
err = r.DeleteAllRetryTasks()
n, err = i.DeleteAllRetryTasks()
case "dead":
err = r.DeleteAllDeadTasks()
n, err = i.DeleteAllDeadTasks()
default:
fmt.Printf("error: `asynq delall [state]` only accepts %v as the argument.\n", delallValidArgs)
os.Exit(1)
@@ -67,5 +68,5 @@ func delall(cmd *cobra.Command, args []string) {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Deleted all tasks in %q state\n", args[0])
fmt.Printf("Deleted all %d tasks in %q state\n", n, args[0])
}

View File

@@ -8,15 +8,14 @@ import (
"fmt"
"os"
"github.com/go-redis/redis/v7"
"github.com/hibiken/asynq/internal/rdb"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// enqCmd represents the enq command
var enqCmd = &cobra.Command{
Use: "enq [task id]",
Use: "enq [task key]",
Short: "Enqueues a task given an identifier",
Long: `Enq (asynq enq) will enqueue a task given an identifier.
@@ -47,27 +46,12 @@ func init() {
}
func enq(cmd *cobra.Command, args []string) {
id, score, qtype, err := parseQueryID(args[0])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
r := rdb.NewRDB(redis.NewClient(&redis.Options{
i := asynq.NewInspector(asynq.RedisClientOpt{
Addr: viper.GetString("uri"),
DB: viper.GetInt("db"),
Password: viper.GetString("password"),
}))
switch qtype {
case "s":
err = r.EnqueueScheduledTask(id, score)
case "r":
err = r.EnqueueRetryTask(id, score)
case "d":
err = r.EnqueueDeadTask(id, score)
default:
fmt.Println("invalid argument")
os.Exit(1)
}
})
err := i.EnqueueTaskByKey(args[0])
if err != nil {
fmt.Println(err)
os.Exit(1)

View File

@@ -8,8 +8,7 @@ import (
"fmt"
"os"
"github.com/go-redis/redis/v7"
"github.com/hibiken/asynq/internal/rdb"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@@ -48,21 +47,22 @@ func init() {
}
func enqall(cmd *cobra.Command, args []string) {
c := redis.NewClient(&redis.Options{
i := asynq.NewInspector(asynq.RedisClientOpt{
Addr: viper.GetString("uri"),
DB: viper.GetInt("db"),
Password: viper.GetString("password"),
})
r := rdb.NewRDB(c)
var n int64
var err error
var (
n int
err error
)
switch args[0] {
case "scheduled":
n, err = r.EnqueueAllScheduledTasks()
n, err = i.EnqueueAllScheduledTasks()
case "retry":
n, err = r.EnqueueAllRetryTasks()
n, err = i.EnqueueAllRetryTasks()
case "dead":
n, err = r.EnqueueAllDeadTasks()
n, err = i.EnqueueAllDeadTasks()
default:
fmt.Printf("error: `asynq enqall [state]` only accepts %v as the argument.\n", enqallValidArgs)
os.Exit(1)

View File

@@ -10,8 +10,7 @@ import (
"strings"
"text/tabwriter"
"github.com/go-redis/redis/v7"
"github.com/hibiken/asynq/internal/rdb"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@@ -38,14 +37,13 @@ func init() {
}
func history(cmd *cobra.Command, args []string) {
c := redis.NewClient(&redis.Options{
i := asynq.NewInspector(asynq.RedisClientOpt{
Addr: viper.GetString("uri"),
DB: viper.GetInt("db"),
Password: viper.GetString("password"),
})
r := rdb.NewRDB(c)
stats, err := r.HistoricalStats(days)
stats, err := i.History(days)
if err != nil {
fmt.Println(err)
os.Exit(1)
@@ -53,7 +51,7 @@ func history(cmd *cobra.Command, args []string) {
printDailyStats(stats)
}
func printDailyStats(stats []*rdb.DailyStats) {
func printDailyStats(stats []*asynq.DailyStats) {
format := strings.Repeat("%v\t", 4) + "\n"
tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0)
fmt.Fprintf(tw, format, "Date (UTC)", "Processed", "Failed", "Error Rate")

View File

@@ -8,15 +8,14 @@ import (
"fmt"
"os"
"github.com/go-redis/redis/v7"
"github.com/hibiken/asynq/internal/rdb"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
// killCmd represents the kill command
var killCmd = &cobra.Command{
Use: "kill [task id]",
Use: "kill [task key]",
Short: "Kills a task given an identifier",
Long: `Kill (asynq kill) will put a task in dead state given an identifier.
@@ -44,25 +43,12 @@ func init() {
}
func kill(cmd *cobra.Command, args []string) {
id, score, qtype, err := parseQueryID(args[0])
if err != nil {
fmt.Println(err)
os.Exit(1)
}
r := rdb.NewRDB(redis.NewClient(&redis.Options{
i := asynq.NewInspector(asynq.RedisClientOpt{
Addr: viper.GetString("uri"),
DB: viper.GetInt("db"),
Password: viper.GetString("password"),
}))
switch qtype {
case "s":
err = r.KillScheduledTask(id, score)
case "r":
err = r.KillRetryTask(id, score)
default:
fmt.Println("invalid argument")
os.Exit(1)
}
})
err := i.KillTaskByKey(args[0])
if err != nil {
fmt.Println(err)
os.Exit(1)

View File

@@ -8,8 +8,7 @@ import (
"fmt"
"os"
"github.com/go-redis/redis/v7"
"github.com/hibiken/asynq/internal/rdb"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@@ -45,19 +44,20 @@ func init() {
}
func killall(cmd *cobra.Command, args []string) {
c := redis.NewClient(&redis.Options{
i := asynq.NewInspector(asynq.RedisClientOpt{
Addr: viper.GetString("uri"),
DB: viper.GetInt("db"),
Password: viper.GetString("password"),
})
r := rdb.NewRDB(c)
var n int64
var err error
var (
n int
err error
)
switch args[0] {
case "scheduled":
n, err = r.KillAllScheduledTasks()
n, err = i.KillAllScheduledTasks()
case "retry":
n, err = r.KillAllRetryTasks()
n, err = i.KillAllRetryTasks()
default:
fmt.Printf("error: `asynq killall [state]` only accepts %v as the argument.\n", killallValidArgs)
os.Exit(1)

View File

@@ -8,13 +8,10 @@ import (
"fmt"
"io"
"os"
"strconv"
"strings"
"time"
"github.com/go-redis/redis/v7"
"github.com/google/uuid"
"github.com/hibiken/asynq/internal/rdb"
"github.com/hibiken/asynq"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@@ -62,12 +59,11 @@ func ls(cmd *cobra.Command, args []string) {
fmt.Println("page number cannot be negative.")
os.Exit(1)
}
c := redis.NewClient(&redis.Options{
i := asynq.NewInspector(asynq.RedisClientOpt{
Addr: viper.GetString("uri"),
DB: viper.GetInt("db"),
Password: viper.GetString("password"),
})
r := rdb.NewRDB(c)
parts := strings.Split(args[0], ":")
switch parts[0] {
case "enqueued":
@@ -75,54 +71,23 @@ func ls(cmd *cobra.Command, args []string) {
fmt.Printf("error: Missing queue name\n`asynq ls enqueued:[queue name]`\n")
os.Exit(1)
}
listEnqueued(r, parts[1])
listEnqueued(i, parts[1])
case "inprogress":
listInProgress(r)
listInProgress(i)
case "scheduled":
listScheduled(r)
listScheduled(i)
case "retry":
listRetry(r)
listRetry(i)
case "dead":
listDead(r)
listDead(i)
default:
fmt.Printf("error: `asynq ls [state]`\nonly accepts %v as the argument.\n", lsValidArgs)
os.Exit(1)
}
}
// queryID returns an identifier used for "enq" command.
// score is the zset score and queryType should be one
// of "s", "r" or "d" (scheduled, retry, dead respectively).
func queryID(id uuid.UUID, score int64, qtype string) string {
const format = "%v:%v:%v"
return fmt.Sprintf(format, qtype, score, id)
}
// parseQueryID is a reverse operation of queryID function.
// It takes a queryID and return each part of id with proper
// type if valid, otherwise it reports an error.
func parseQueryID(queryID string) (id uuid.UUID, score int64, qtype string, err error) {
parts := strings.Split(queryID, ":")
if len(parts) != 3 {
return uuid.Nil, 0, "", fmt.Errorf("invalid id")
}
id, err = uuid.Parse(parts[2])
if err != nil {
return uuid.Nil, 0, "", fmt.Errorf("invalid id")
}
score, err = strconv.ParseInt(parts[1], 10, 64)
if err != nil {
return uuid.Nil, 0, "", fmt.Errorf("invalid id")
}
qtype = parts[0]
if len(qtype) != 1 || !strings.Contains("srd", qtype) {
return uuid.Nil, 0, "", fmt.Errorf("invalid id")
}
return id, score, qtype, nil
}
func listEnqueued(r *rdb.RDB, qname string) {
tasks, err := r.ListEnqueued(qname, rdb.Pagination{Size: pageSize, Page: pageNum})
func listEnqueued(i *asynq.Inspector, qname string) {
tasks, err := i.ListEnqueuedTasks(qname, asynq.PageSize(pageSize), asynq.Page(pageNum))
if err != nil {
fmt.Println(err)
os.Exit(1)
@@ -132,17 +97,16 @@ func listEnqueued(r *rdb.RDB, qname string) {
return
}
cols := []string{"ID", "Type", "Payload", "Queue"}
printRows := func(w io.Writer, tmpl string) {
printTable(cols, func(w io.Writer, tmpl string) {
for _, t := range tasks {
fmt.Fprintf(w, tmpl, t.ID, t.Type, t.Payload, t.Queue)
}
}
printTable(cols, printRows)
})
fmt.Printf("\nShowing %d tasks from page %d\n", len(tasks), pageNum)
}
func listInProgress(r *rdb.RDB) {
tasks, err := r.ListInProgress(rdb.Pagination{Size: pageSize, Page: pageNum})
func listInProgress(i *asynq.Inspector) {
tasks, err := i.ListInProgressTasks(asynq.PageSize(pageSize), asynq.Page(pageNum))
if err != nil {
fmt.Println(err)
os.Exit(1)
@@ -152,17 +116,16 @@ func listInProgress(r *rdb.RDB) {
return
}
cols := []string{"ID", "Type", "Payload"}
printRows := func(w io.Writer, tmpl string) {
printTable(cols, func(w io.Writer, tmpl string) {
for _, t := range tasks {
fmt.Fprintf(w, tmpl, t.ID, t.Type, t.Payload)
}
}
printTable(cols, printRows)
})
fmt.Printf("\nShowing %d tasks from page %d\n", len(tasks), pageNum)
}
func listScheduled(r *rdb.RDB) {
tasks, err := r.ListScheduled(rdb.Pagination{Size: pageSize, Page: pageNum})
func listScheduled(i *asynq.Inspector) {
tasks, err := i.ListScheduledTasks(asynq.PageSize(pageSize), asynq.Page(pageNum))
if err != nil {
fmt.Println(err)
os.Exit(1)
@@ -171,19 +134,19 @@ func listScheduled(r *rdb.RDB) {
fmt.Println("No scheduled tasks")
return
}
cols := []string{"ID", "Type", "Payload", "Process In", "Queue"}
printRows := func(w io.Writer, tmpl string) {
cols := []string{"Key", "Type", "Payload", "Process In", "Queue"}
printTable(cols, func(w io.Writer, tmpl string) {
for _, t := range tasks {
processIn := fmt.Sprintf("%.0f seconds", t.ProcessAt.Sub(time.Now()).Seconds())
fmt.Fprintf(w, tmpl, queryID(t.ID, t.Score, "s"), t.Type, t.Payload, processIn, t.Queue)
processIn := fmt.Sprintf("%.0f seconds",
t.NextEnqueueAt.Sub(time.Now()).Seconds())
fmt.Fprintf(w, tmpl, t.Key(), t.Type, t.Payload, processIn, t.Queue)
}
}
printTable(cols, printRows)
})
fmt.Printf("\nShowing %d tasks from page %d\n", len(tasks), pageNum)
}
func listRetry(r *rdb.RDB) {
tasks, err := r.ListRetry(rdb.Pagination{Size: pageSize, Page: pageNum})
func listRetry(i *asynq.Inspector) {
tasks, err := i.ListRetryTasks(asynq.PageSize(pageSize), asynq.Page(pageNum))
if err != nil {
fmt.Println(err)
os.Exit(1)
@@ -192,24 +155,23 @@ func listRetry(r *rdb.RDB) {
fmt.Println("No retry tasks")
return
}
cols := []string{"ID", "Type", "Payload", "Next Retry", "Last Error", "Retried", "Max Retry", "Queue"}
printRows := func(w io.Writer, tmpl string) {
cols := []string{"Key", "Type", "Payload", "Next Retry", "Last Error", "Retried", "Max Retry", "Queue"}
printTable(cols, func(w io.Writer, tmpl string) {
for _, t := range tasks {
var nextRetry string
if d := t.ProcessAt.Sub(time.Now()); d > 0 {
if d := t.NextEnqueueAt.Sub(time.Now()); d > 0 {
nextRetry = fmt.Sprintf("in %v", d.Round(time.Second))
} else {
nextRetry = "right now"
}
fmt.Fprintf(w, tmpl, queryID(t.ID, t.Score, "r"), t.Type, t.Payload, nextRetry, t.ErrorMsg, t.Retried, t.Retry, t.Queue)
fmt.Fprintf(w, tmpl, t.Key(), t.Type, t.Payload, nextRetry, t.ErrorMsg, t.Retried, t.MaxRetry, t.Queue)
}
}
printTable(cols, printRows)
})
fmt.Printf("\nShowing %d tasks from page %d\n", len(tasks), pageNum)
}
func listDead(r *rdb.RDB) {
tasks, err := r.ListDead(rdb.Pagination{Size: pageSize, Page: pageNum})
func listDead(i *asynq.Inspector) {
tasks, err := i.ListDeadTasks(asynq.PageSize(pageSize), asynq.Page(pageNum))
if err != nil {
fmt.Println(err)
os.Exit(1)
@@ -218,12 +180,11 @@ func listDead(r *rdb.RDB) {
fmt.Println("No dead tasks")
return
}
cols := []string{"ID", "Type", "Payload", "Last Failed", "Last Error", "Queue"}
printRows := func(w io.Writer, tmpl string) {
cols := []string{"Key", "Type", "Payload", "Last Failed", "Last Error", "Queue"}
printTable(cols, func(w io.Writer, tmpl string) {
for _, t := range tasks {
fmt.Fprintf(w, tmpl, queryID(t.ID, t.Score, "d"), t.Type, t.Payload, t.LastFailedAt, t.ErrorMsg, t.Queue)
fmt.Fprintf(w, tmpl, t.Key(), t.Type, t.Payload, t.LastFailedAt, t.ErrorMsg, t.Queue)
}
}
printTable(cols, printRows)
})
fmt.Printf("\nShowing %d tasks from page %d\n", len(tasks), pageNum)
}