mirror of
https://github.com/hibiken/asynq.git
synced 2024-12-26 07:42:17 +08:00
(cli): Improve help command output
This commit is contained in:
parent
9116c096ec
commit
4dd2b5738a
@ -11,6 +11,7 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
@ -24,21 +25,30 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var cronCmd = &cobra.Command{
|
var cronCmd = &cobra.Command{
|
||||||
Use: "cron",
|
Use: "cron <command> [flags]",
|
||||||
Short: "Manage cron",
|
Short: "Manage cron",
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq cron ls
|
||||||
|
$ asynq cron history 7837f142-6337-4217-9276-8f27281b67d1`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var cronListCmd = &cobra.Command{
|
var cronListCmd = &cobra.Command{
|
||||||
Use: "ls",
|
Use: "list",
|
||||||
Short: "List cron entries",
|
Aliases: []string{"ls"},
|
||||||
Run: cronList,
|
Short: "List cron entries",
|
||||||
|
Run: cronList,
|
||||||
}
|
}
|
||||||
|
|
||||||
var cronHistoryCmd = &cobra.Command{
|
var cronHistoryCmd = &cobra.Command{
|
||||||
Use: "history [ENTRY_ID...]",
|
Use: "history <entry_id> [<entry_id>...]",
|
||||||
Short: "Show history of each cron tasks",
|
Short: "Show history of each cron tasks",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: cronHistory,
|
Run: cronHistory,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq cron history 7837f142-6337-4217-9276-8f27281b67d1
|
||||||
|
$ asynq cron history 7837f142-6337-4217-9276-8f27281b67d1 bf6a8594-cd03-4968-b36a-8572c5e160dd
|
||||||
|
$ asynq cron history 7837f142-6337-4217-9276-8f27281b67d1 --size=100
|
||||||
|
$ asynq cron history 7837f142-6337-4217-9276-8f27281b67d1 --page=2`),
|
||||||
}
|
}
|
||||||
|
|
||||||
func cronList(cmd *cobra.Command, args []string) {
|
func cronList(cmd *cobra.Command, args []string) {
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,15 +20,18 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var groupCmd = &cobra.Command{
|
var groupCmd = &cobra.Command{
|
||||||
Use: "group",
|
Use: "group <command> [flags]",
|
||||||
Short: "Manage groups",
|
Short: "Manage groups",
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq group list --queue=myqueue`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var groupListCmd = &cobra.Command{
|
var groupListCmd = &cobra.Command{
|
||||||
Use: "ls",
|
Use: "list",
|
||||||
Short: "List groups",
|
Aliases: []string{"ls"},
|
||||||
Args: cobra.NoArgs,
|
Short: "List groups",
|
||||||
Run: groupLists,
|
Args: cobra.NoArgs,
|
||||||
|
Run: groupLists,
|
||||||
}
|
}
|
||||||
|
|
||||||
func groupLists(cmd *cobra.Command, args []string) {
|
func groupLists(cmd *cobra.Command, args []string) {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
"github.com/hibiken/asynq/internal/errors"
|
"github.com/hibiken/asynq/internal/errors"
|
||||||
@ -31,51 +32,75 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var queueCmd = &cobra.Command{
|
var queueCmd = &cobra.Command{
|
||||||
Use: "queue",
|
Use: "queue <command> [flags]",
|
||||||
Short: "Manage queues",
|
Short: "Manage queues",
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq queue ls
|
||||||
|
$ asynq queue inspect myqueue
|
||||||
|
$ asynq queue pause myqueue`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var queueListCmd = &cobra.Command{
|
var queueListCmd = &cobra.Command{
|
||||||
Use: "ls",
|
Use: "list",
|
||||||
Short: "List queues",
|
Short: "List queues",
|
||||||
|
Aliases: []string{"ls"},
|
||||||
// TODO: Use RunE instead?
|
// TODO: Use RunE instead?
|
||||||
Run: queueList,
|
Run: queueList,
|
||||||
}
|
}
|
||||||
|
|
||||||
var queueInspectCmd = &cobra.Command{
|
var queueInspectCmd = &cobra.Command{
|
||||||
Use: "inspect QUEUE [QUEUE...]",
|
Use: "inspect <queue> [<queue>...]",
|
||||||
Short: "Display detailed information on one or more queues",
|
Short: "Display detailed information on one or more queues",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
// TODO: Use RunE instead?
|
// TODO: Use RunE instead?
|
||||||
Run: queueInspect,
|
Run: queueInspect,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq queue inspect myqueue
|
||||||
|
$ asynq queue inspect queue1 queue2 queue3`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var queueHistoryCmd = &cobra.Command{
|
var queueHistoryCmd = &cobra.Command{
|
||||||
Use: "history QUEUE [QUEUE...]",
|
Use: "history <queue> [<queue>...]",
|
||||||
Short: "Display historical aggregate data from one or more queues",
|
Short: "Display historical aggregate data from one or more queues",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: queueHistory,
|
Run: queueHistory,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq queue history myqueue
|
||||||
|
$ asynq queue history queue1 queue2 queue3
|
||||||
|
$ asynq queue history myqueue --days=90`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var queuePauseCmd = &cobra.Command{
|
var queuePauseCmd = &cobra.Command{
|
||||||
Use: "pause QUEUE [QUEUE...]",
|
Use: "pause <queue> [<queue>...]",
|
||||||
Short: "Pause one or more queues",
|
Short: "Pause one or more queues",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: queuePause,
|
Run: queuePause,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq queue pause myqueue
|
||||||
|
$ asynq queue pause queue1 queue2 queue3`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var queueUnpauseCmd = &cobra.Command{
|
var queueUnpauseCmd = &cobra.Command{
|
||||||
Use: "unpause QUEUE [QUEUE...]",
|
Use: "resume <queue> [<queue>...]",
|
||||||
Short: "Unpause one or more queues",
|
Short: "Resume (unpause) one or more queues",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: queueUnpause,
|
Aliases: []string{"unpause"},
|
||||||
|
Run: queueUnpause,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq queue resume myqueue
|
||||||
|
$ asynq queue resume queue1 queue2 queue3`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var queueRemoveCmd = &cobra.Command{
|
var queueRemoveCmd = &cobra.Command{
|
||||||
Use: "rm QUEUE [QUEUE...]",
|
Use: "remove <queue> [<queue>...]",
|
||||||
Short: "Remove one or more queues",
|
Short: "Remove one or more queues",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Aliases: []string{"rm", "delete"},
|
||||||
Run: queueRemove,
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
Run: queueRemove,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq queue rm myqueue
|
||||||
|
$ asynq queue rm queue1 queue2 queue3
|
||||||
|
$ asynq queue rm myqueue --force`),
|
||||||
}
|
}
|
||||||
|
|
||||||
func queueList(cmd *cobra.Command, args []string) {
|
func queueList(cmd *cobra.Command, args []string) {
|
||||||
|
@ -14,11 +14,15 @@ import (
|
|||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
|
"github.com/fatih/color"
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
"github.com/hibiken/asynq/internal/base"
|
"github.com/hibiken/asynq/internal/base"
|
||||||
"github.com/hibiken/asynq/internal/rdb"
|
"github.com/hibiken/asynq/internal/rdb"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
"golang.org/x/exp/utf8string"
|
||||||
|
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@ -39,10 +43,22 @@ var (
|
|||||||
|
|
||||||
// rootCmd represents the base command when called without any subcommands
|
// rootCmd represents the base command when called without any subcommands
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "asynq",
|
Use: "asynq <command> <subcommand> [flags]",
|
||||||
Short: "A monitoring tool for asynq queues",
|
Short: "Asynq CLI",
|
||||||
Long: `Asynq is a montoring CLI to inspect tasks and queues managed by asynq.`,
|
Long: `Command line tool to inspect tasks and queues managed by Asynq`,
|
||||||
Version: base.Version,
|
Version: base.Version,
|
||||||
|
|
||||||
|
SilenceUsage: true,
|
||||||
|
SilenceErrors: true,
|
||||||
|
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq stats
|
||||||
|
$ asynq queue pause myqueue
|
||||||
|
$ asynq task list --queue=myqueue --state=archived`),
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"help:feedback": heredoc.Doc(`
|
||||||
|
Open an issue at https://github.com/hibiken/asynq/issues/new/choose`),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var versionOutput = fmt.Sprintf("asynq version %s\n", base.Version)
|
var versionOutput = fmt.Sprintf("asynq version %s\n", base.Version)
|
||||||
@ -64,22 +80,233 @@ func Execute() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRootCmd(cmd *cobra.Command) bool {
|
||||||
|
return cmd != nil && !cmd.HasParent()
|
||||||
|
}
|
||||||
|
|
||||||
|
// displayLine represents a line displayed in the output as '<name> <desc>',
|
||||||
|
// where pad is used to pad the name from desc.
|
||||||
|
type displayLine struct {
|
||||||
|
name string
|
||||||
|
desc string
|
||||||
|
pad int // number of rpad
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *displayLine) String() string {
|
||||||
|
return rpad(l.name, l.pad) + l.desc
|
||||||
|
}
|
||||||
|
|
||||||
|
type displayLines []*displayLine
|
||||||
|
|
||||||
|
func (dls displayLines) String() string {
|
||||||
|
var lines []string
|
||||||
|
for _, dl := range dls {
|
||||||
|
lines = append(lines, dl.String())
|
||||||
|
}
|
||||||
|
return strings.Join(lines, "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capitalize the first word in the given string.
|
||||||
|
func capitalize(s string) string {
|
||||||
|
str := utf8string.NewString(s)
|
||||||
|
if str.RuneCount() == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var b strings.Builder
|
||||||
|
b.WriteString(strings.ToUpper(string(str.At(0))))
|
||||||
|
b.WriteString(str.Slice(1, str.RuneCount()))
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func rootHelpFunc(cmd *cobra.Command, args []string) {
|
||||||
|
// Display helpful error message when user mistypes a subcommand (e.g. 'asynq queue lst').
|
||||||
|
if isRootCmd(cmd.Parent()) && len(args) >= 2 && args[1] != "--help" && args[1] != "-h" {
|
||||||
|
printSubcommandSuggestions(cmd, args[1])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var lines []*displayLine
|
||||||
|
var commands []*displayLine
|
||||||
|
for _, c := range cmd.Commands() {
|
||||||
|
if c.Hidden || c.Short == "" || c.Name() == "help" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
l := &displayLine{name: c.Name() + ":", desc: capitalize(c.Short)}
|
||||||
|
commands = append(commands, l)
|
||||||
|
lines = append(lines, l)
|
||||||
|
}
|
||||||
|
var localFlags []*displayLine
|
||||||
|
cmd.LocalFlags().VisitAll(func(f *pflag.Flag) {
|
||||||
|
l := &displayLine{name: "--" + f.Name, desc: capitalize(f.Usage)}
|
||||||
|
localFlags = append(localFlags, l)
|
||||||
|
lines = append(lines, l)
|
||||||
|
})
|
||||||
|
var inheritedFlags []*displayLine
|
||||||
|
cmd.InheritedFlags().VisitAll(func(f *pflag.Flag) {
|
||||||
|
l := &displayLine{name: "--" + f.Name, desc: capitalize(f.Usage)}
|
||||||
|
inheritedFlags = append(inheritedFlags, l)
|
||||||
|
lines = append(lines, l)
|
||||||
|
})
|
||||||
|
adjustPadding(lines...)
|
||||||
|
|
||||||
|
type helpEntry struct {
|
||||||
|
Title string
|
||||||
|
Body string
|
||||||
|
}
|
||||||
|
var helpEntries []*helpEntry
|
||||||
|
desc := cmd.Long
|
||||||
|
if desc == "" {
|
||||||
|
desc = cmd.Short
|
||||||
|
}
|
||||||
|
if desc != "" {
|
||||||
|
helpEntries = append(helpEntries, &helpEntry{"", desc})
|
||||||
|
}
|
||||||
|
helpEntries = append(helpEntries, &helpEntry{"USAGE", cmd.UseLine()})
|
||||||
|
if len(commands) > 0 {
|
||||||
|
helpEntries = append(helpEntries, &helpEntry{"COMMANDS", displayLines(commands).String()})
|
||||||
|
}
|
||||||
|
if cmd.LocalFlags().HasFlags() {
|
||||||
|
helpEntries = append(helpEntries, &helpEntry{"FLAGS", displayLines(localFlags).String()})
|
||||||
|
}
|
||||||
|
if cmd.InheritedFlags().HasFlags() {
|
||||||
|
helpEntries = append(helpEntries, &helpEntry{"INHERITED FLAGS", displayLines(inheritedFlags).String()})
|
||||||
|
}
|
||||||
|
if cmd.Example != "" {
|
||||||
|
helpEntries = append(helpEntries, &helpEntry{"EXAMPLES", cmd.Example})
|
||||||
|
}
|
||||||
|
helpEntries = append(helpEntries, &helpEntry{"LEARN MORE", heredoc.Doc(`
|
||||||
|
Use 'asynq <command> <subcommand> --help' for more information about a command.`)})
|
||||||
|
if s, ok := cmd.Annotations["help:feedback"]; ok {
|
||||||
|
helpEntries = append(helpEntries, &helpEntry{"FEEDBACK", s})
|
||||||
|
}
|
||||||
|
|
||||||
|
out := cmd.OutOrStdout()
|
||||||
|
bold := color.New(color.Bold)
|
||||||
|
for _, e := range helpEntries {
|
||||||
|
if e.Title != "" {
|
||||||
|
// If there is a title, add indentation to each line in the body
|
||||||
|
bold.Fprintln(out, e.Title)
|
||||||
|
fmt.Fprintln(out, indent(e.Body, 2 /* spaces */))
|
||||||
|
} else {
|
||||||
|
// If there is no title, print the body as is
|
||||||
|
fmt.Fprintln(out, e.Body)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rootUsageFunc(cmd *cobra.Command) error {
|
||||||
|
out := cmd.OutOrStdout()
|
||||||
|
fmt.Fprintf(out, "Usage: %s", cmd.UseLine())
|
||||||
|
if subcmds := cmd.Commands(); len(subcmds) > 0 {
|
||||||
|
fmt.Fprint(out, "\n\nAvailable commands:\n")
|
||||||
|
for _, c := range subcmds {
|
||||||
|
if c.Hidden {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fmt.Fprintf(out, " %s\n", c.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var localFlags []*displayLine
|
||||||
|
cmd.LocalFlags().VisitAll(func(f *pflag.Flag) {
|
||||||
|
localFlags = append(localFlags, &displayLine{name: "--" + f.Name, desc: capitalize(f.Usage)})
|
||||||
|
})
|
||||||
|
adjustPadding(localFlags...)
|
||||||
|
if len(localFlags) > 0 {
|
||||||
|
fmt.Fprint(out, "\n\nFlags:\n")
|
||||||
|
for _, l := range localFlags {
|
||||||
|
fmt.Fprintf(out, " %s\n", l.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printSubcommandSuggestions(cmd *cobra.Command, arg string) {
|
||||||
|
out := cmd.OutOrStdout()
|
||||||
|
fmt.Fprintf(out, "unknown command %q for %q\n", arg, cmd.CommandPath())
|
||||||
|
if cmd.SuggestionsMinimumDistance <= 0 {
|
||||||
|
cmd.SuggestionsMinimumDistance = 2
|
||||||
|
}
|
||||||
|
candidates := cmd.SuggestionsFor(arg)
|
||||||
|
if len(candidates) > 0 {
|
||||||
|
fmt.Fprint(out, "\nDid you mean this?\n")
|
||||||
|
for _, c := range candidates {
|
||||||
|
fmt.Fprintf(out, "\t%s\n", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Fprintln(out)
|
||||||
|
rootUsageFunc(cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func adjustPadding(lines ...*displayLine) {
|
||||||
|
// find the maximum width of the name
|
||||||
|
max := 0
|
||||||
|
for _, l := range lines {
|
||||||
|
if n := utf8.RuneCountInString(l.name); n > max {
|
||||||
|
max = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, l := range lines {
|
||||||
|
l.pad = max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rpad adds padding to the right of a string.
|
||||||
|
func rpad(s string, padding int) string {
|
||||||
|
tmpl := fmt.Sprintf("%%-%ds ", padding)
|
||||||
|
return fmt.Sprintf(tmpl, s)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// indent indents the given text by given spaces.
|
||||||
|
func indent(text string, space int) string {
|
||||||
|
if len(text) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var b strings.Builder
|
||||||
|
indentation := strings.Repeat(" ", space)
|
||||||
|
lastRune := '\n'
|
||||||
|
for _, r := range text {
|
||||||
|
if lastRune == '\n' {
|
||||||
|
b.WriteString(indentation)
|
||||||
|
}
|
||||||
|
b.WriteRune(r)
|
||||||
|
lastRune = r
|
||||||
|
}
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// dedent removes any indentation from the given text.
|
||||||
|
func dedent(text string) string {
|
||||||
|
lines := strings.Split(text, "\n")
|
||||||
|
var b strings.Builder
|
||||||
|
for _, l := range lines {
|
||||||
|
b.WriteString(strings.TrimLeftFunc(l, unicode.IsSpace))
|
||||||
|
b.WriteRune('\n')
|
||||||
|
}
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cobra.OnInitialize(initConfig)
|
cobra.OnInitialize(initConfig)
|
||||||
|
|
||||||
|
rootCmd.SetHelpFunc(rootHelpFunc)
|
||||||
|
rootCmd.SetUsageFunc(rootUsageFunc)
|
||||||
|
|
||||||
rootCmd.AddCommand(versionCmd)
|
rootCmd.AddCommand(versionCmd)
|
||||||
rootCmd.SetVersionTemplate(versionOutput)
|
rootCmd.SetVersionTemplate(versionOutput)
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file to set flag defaut values (default is $HOME/.asynq.yaml)")
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "Config file to set flag defaut values (default is $HOME/.asynq.yaml)")
|
||||||
rootCmd.PersistentFlags().StringVarP(&uri, "uri", "u", "127.0.0.1:6379", "redis server URI")
|
rootCmd.PersistentFlags().StringVarP(&uri, "uri", "u", "127.0.0.1:6379", "Redis server URI")
|
||||||
rootCmd.PersistentFlags().IntVarP(&db, "db", "n", 0, "redis database number (default is 0)")
|
rootCmd.PersistentFlags().IntVarP(&db, "db", "n", 0, "Redis database number (default is 0)")
|
||||||
rootCmd.PersistentFlags().StringVarP(&password, "password", "p", "", "password to use when connecting to redis server")
|
rootCmd.PersistentFlags().StringVarP(&password, "password", "p", "", "Password to use when connecting to redis server")
|
||||||
rootCmd.PersistentFlags().BoolVar(&useRedisCluster, "cluster", false, "connect to redis cluster")
|
rootCmd.PersistentFlags().BoolVar(&useRedisCluster, "cluster", false, "Connect to redis cluster")
|
||||||
rootCmd.PersistentFlags().StringVar(&clusterAddrs, "cluster_addrs",
|
rootCmd.PersistentFlags().StringVar(&clusterAddrs, "cluster_addrs",
|
||||||
"127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005",
|
"127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003,127.0.0.1:7004,127.0.0.1:7005",
|
||||||
"list of comma-separated redis server addresses")
|
"List of comma-separated redis server addresses")
|
||||||
rootCmd.PersistentFlags().StringVar(&tlsServerName, "tls_server",
|
rootCmd.PersistentFlags().StringVar(&tlsServerName, "tls_server",
|
||||||
"", "server name for TLS validation")
|
"", "Server name for TLS validation")
|
||||||
// Bind flags with config.
|
// Bind flags with config.
|
||||||
viper.BindPFlag("uri", rootCmd.PersistentFlags().Lookup("uri"))
|
viper.BindPFlag("uri", rootCmd.PersistentFlags().Lookup("uri"))
|
||||||
viper.BindPFlag("db", rootCmd.PersistentFlags().Lookup("db"))
|
viper.BindPFlag("db", rootCmd.PersistentFlags().Lookup("db"))
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,13 +22,16 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var serverCmd = &cobra.Command{
|
var serverCmd = &cobra.Command{
|
||||||
Use: "server",
|
Use: "server <command> [flags]",
|
||||||
Short: "Manage servers",
|
Short: "Manage servers",
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq server list`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var serverListCmd = &cobra.Command{
|
var serverListCmd = &cobra.Command{
|
||||||
Use: "ls",
|
Use: "list",
|
||||||
Short: "List servers",
|
Aliases: []string{"ls"},
|
||||||
|
Short: "List servers",
|
||||||
Long: `Server list (asynq server ls) shows all running worker servers
|
Long: `Server list (asynq server ls) shows all running worker servers
|
||||||
pulling tasks from the given redis instance.
|
pulling tasks from the given redis instance.
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/hibiken/asynq/internal/rdb"
|
"github.com/hibiken/asynq/internal/rdb"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -24,19 +25,15 @@ import (
|
|||||||
// statsCmd represents the stats command
|
// statsCmd represents the stats command
|
||||||
var statsCmd = &cobra.Command{
|
var statsCmd = &cobra.Command{
|
||||||
Use: "stats",
|
Use: "stats",
|
||||||
Short: "Shows current state of the tasks and queues",
|
Short: "View current state",
|
||||||
Long: `Stats (aysnq stats) will show the overview of tasks and queues at that instant.
|
Long: heredoc.Doc(`
|
||||||
|
Stats shows the overview of tasks and queues at that instant.
|
||||||
|
|
||||||
Specifically, the command shows the following:
|
The command shows the following:
|
||||||
* Number of tasks in each state
|
* Number of tasks in each state
|
||||||
* Number of tasks in each queue
|
* Number of tasks in each queue
|
||||||
* Aggregate data for the current day
|
* Aggregate data for the current day
|
||||||
* Basic information about the running redis instance
|
* Basic information about the running redis instance`),
|
||||||
|
|
||||||
To monitor the tasks continuously, it's recommended that you run this
|
|
||||||
command in conjunction with the watch command.
|
|
||||||
|
|
||||||
Example: watch -n 3 asynq stats -> Shows current state of tasks every three seconds`,
|
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: stats,
|
Run: stats,
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc/v2"
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/hibiken/asynq"
|
"github.com/hibiken/asynq"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -18,8 +19,8 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(taskCmd)
|
rootCmd.AddCommand(taskCmd)
|
||||||
taskCmd.AddCommand(taskListCmd)
|
taskCmd.AddCommand(taskListCmd)
|
||||||
taskListCmd.Flags().StringP("queue", "q", "", "queue to inspect")
|
taskListCmd.Flags().StringP("queue", "q", "", "queue to inspect (required)")
|
||||||
taskListCmd.Flags().StringP("state", "s", "", "state of the tasks to inspect")
|
taskListCmd.Flags().StringP("state", "s", "", "state of the tasks; one of { active | pending | aggregating | scheduled | retry | archived | completed } (required)")
|
||||||
taskListCmd.Flags().Int("page", 1, "page number")
|
taskListCmd.Flags().Int("page", 1, "page number")
|
||||||
taskListCmd.Flags().Int("size", 30, "page size")
|
taskListCmd.Flags().Int("size", 30, "page size")
|
||||||
taskListCmd.Flags().StringP("group", "g", "", "group to inspect (required for listing aggregating tasks)")
|
taskListCmd.Flags().StringP("group", "g", "", "group to inspect (required for listing aggregating tasks)")
|
||||||
@ -29,141 +30,155 @@ func init() {
|
|||||||
taskCmd.AddCommand(taskCancelCmd)
|
taskCmd.AddCommand(taskCancelCmd)
|
||||||
|
|
||||||
taskCmd.AddCommand(taskInspectCmd)
|
taskCmd.AddCommand(taskInspectCmd)
|
||||||
taskInspectCmd.Flags().StringP("queue", "q", "", "queue to which the task belongs")
|
taskInspectCmd.Flags().StringP("queue", "q", "", "queue to which the task belongs (required)")
|
||||||
taskInspectCmd.Flags().StringP("id", "i", "", "id of the task")
|
taskInspectCmd.Flags().StringP("id", "i", "", "id of the task (required)")
|
||||||
taskInspectCmd.MarkFlagRequired("queue")
|
taskInspectCmd.MarkFlagRequired("queue")
|
||||||
taskInspectCmd.MarkFlagRequired("id")
|
taskInspectCmd.MarkFlagRequired("id")
|
||||||
|
|
||||||
taskCmd.AddCommand(taskArchiveCmd)
|
taskCmd.AddCommand(taskArchiveCmd)
|
||||||
taskArchiveCmd.Flags().StringP("queue", "q", "", "queue to which the task belongs")
|
taskArchiveCmd.Flags().StringP("queue", "q", "", "queue to which the task belongs (required)")
|
||||||
taskArchiveCmd.Flags().StringP("id", "i", "", "id of the task")
|
taskArchiveCmd.Flags().StringP("id", "i", "", "id of the task (required)")
|
||||||
taskArchiveCmd.MarkFlagRequired("queue")
|
taskArchiveCmd.MarkFlagRequired("queue")
|
||||||
taskArchiveCmd.MarkFlagRequired("id")
|
taskArchiveCmd.MarkFlagRequired("id")
|
||||||
|
|
||||||
taskCmd.AddCommand(taskDeleteCmd)
|
taskCmd.AddCommand(taskDeleteCmd)
|
||||||
taskDeleteCmd.Flags().StringP("queue", "q", "", "queue to which the task belongs")
|
taskDeleteCmd.Flags().StringP("queue", "q", "", "queue to which the task belongs (required)")
|
||||||
taskDeleteCmd.Flags().StringP("id", "i", "", "id of the task")
|
taskDeleteCmd.Flags().StringP("id", "i", "", "id of the task (required)")
|
||||||
taskDeleteCmd.MarkFlagRequired("queue")
|
taskDeleteCmd.MarkFlagRequired("queue")
|
||||||
taskDeleteCmd.MarkFlagRequired("id")
|
taskDeleteCmd.MarkFlagRequired("id")
|
||||||
|
|
||||||
taskCmd.AddCommand(taskRunCmd)
|
taskCmd.AddCommand(taskRunCmd)
|
||||||
taskRunCmd.Flags().StringP("queue", "q", "", "queue to which the task belongs")
|
taskRunCmd.Flags().StringP("queue", "q", "", "queue to which the task belongs (required)")
|
||||||
taskRunCmd.Flags().StringP("id", "i", "", "id of the task")
|
taskRunCmd.Flags().StringP("id", "i", "", "id of the task (required)")
|
||||||
taskRunCmd.MarkFlagRequired("queue")
|
taskRunCmd.MarkFlagRequired("queue")
|
||||||
taskRunCmd.MarkFlagRequired("id")
|
taskRunCmd.MarkFlagRequired("id")
|
||||||
|
|
||||||
taskCmd.AddCommand(taskArchiveAllCmd)
|
taskCmd.AddCommand(taskArchiveAllCmd)
|
||||||
taskArchiveAllCmd.Flags().StringP("queue", "q", "", "queue to which the tasks belong")
|
taskArchiveAllCmd.Flags().StringP("queue", "q", "", "queue to which the tasks belong (required)")
|
||||||
taskArchiveAllCmd.Flags().StringP("state", "s", "", "state of the tasks")
|
taskArchiveAllCmd.Flags().StringP("state", "s", "", "state of the tasks; one of { pending | aggregating | scheduled | retry } (required)")
|
||||||
taskArchiveAllCmd.MarkFlagRequired("queue")
|
taskArchiveAllCmd.MarkFlagRequired("queue")
|
||||||
taskArchiveAllCmd.MarkFlagRequired("state")
|
taskArchiveAllCmd.MarkFlagRequired("state")
|
||||||
|
taskArchiveAllCmd.Flags().StringP("group", "g", "", "group to which the tasks belong (required for archiving aggregating tasks)")
|
||||||
|
|
||||||
taskCmd.AddCommand(taskDeleteAllCmd)
|
taskCmd.AddCommand(taskDeleteAllCmd)
|
||||||
taskDeleteAllCmd.Flags().StringP("queue", "q", "", "queue to which the tasks belong")
|
taskDeleteAllCmd.Flags().StringP("queue", "q", "", "queue to which the tasks belong (required)")
|
||||||
taskDeleteAllCmd.Flags().StringP("state", "s", "", "state of the tasks")
|
taskDeleteAllCmd.Flags().StringP("state", "s", "", "state of the tasks; one of { pending | aggregating | scheduled | retry | archived | completed } (required)")
|
||||||
taskDeleteAllCmd.MarkFlagRequired("queue")
|
taskDeleteAllCmd.MarkFlagRequired("queue")
|
||||||
taskDeleteAllCmd.MarkFlagRequired("state")
|
taskDeleteAllCmd.MarkFlagRequired("state")
|
||||||
|
taskDeleteAllCmd.Flags().StringP("group", "g", "", "group to which the tasks belong (required for deleting aggregating tasks)")
|
||||||
|
|
||||||
taskCmd.AddCommand(taskRunAllCmd)
|
taskCmd.AddCommand(taskRunAllCmd)
|
||||||
taskRunAllCmd.Flags().StringP("queue", "q", "", "queue to which the tasks belong")
|
taskRunAllCmd.Flags().StringP("queue", "q", "", "queue to which the tasks belong (required)")
|
||||||
taskRunAllCmd.Flags().StringP("state", "s", "", "state of the tasks")
|
taskRunAllCmd.Flags().StringP("state", "s", "", "state of the tasks; one of { scheduled | retry | archived } (required)")
|
||||||
taskRunAllCmd.MarkFlagRequired("queue")
|
taskRunAllCmd.MarkFlagRequired("queue")
|
||||||
taskRunAllCmd.MarkFlagRequired("state")
|
taskRunAllCmd.MarkFlagRequired("state")
|
||||||
|
taskRunAllCmd.Flags().StringP("group", "g", "", "group to which the tasks belong (required for running aggregating tasks)")
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskCmd = &cobra.Command{
|
var taskCmd = &cobra.Command{
|
||||||
Use: "task",
|
Use: "task <command> [flags]",
|
||||||
Short: "Manage tasks",
|
Short: "Manage tasks",
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task list --queue=myqueue --state=scheduled
|
||||||
|
$ asynq task inspect --queue=myqueue --id=7837f142-6337-4217-9276-8f27281b67d1
|
||||||
|
$ asynq task delete --queue=myqueue --id=7837f142-6337-4217-9276-8f27281b67d1
|
||||||
|
$ asynq task deleteall --queue=myqueue --state=archived`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskListCmd = &cobra.Command{
|
var taskListCmd = &cobra.Command{
|
||||||
Use: "ls --queue=QUEUE --state=STATE",
|
Use: "list --queue=<queue> --state=<state> [flags]",
|
||||||
Short: "List tasks",
|
Aliases: []string{"ls"},
|
||||||
Long: `List tasks of the given state from the specified queue.
|
Short: "List tasks",
|
||||||
|
Long: heredoc.Doc(`
|
||||||
|
List tasks of the given state from the specified queue.
|
||||||
|
|
||||||
The value for the state flag should be one of:
|
The --queue and --state flags are required.
|
||||||
- active
|
|
||||||
- pending
|
|
||||||
- aggregating
|
|
||||||
- scheduled
|
|
||||||
- retry
|
|
||||||
- archived
|
|
||||||
- completed
|
|
||||||
|
|
||||||
List opeartion paginates the result set.
|
Note: For aggregating tasks, additional --group flag is required.
|
||||||
By default, the command fetches the first 30 tasks.
|
|
||||||
Use --page and --size flags to specify the page number and size.
|
|
||||||
|
|
||||||
|
List opeartion paginates the result set. By default, the command fetches the first 30 tasks.
|
||||||
Example:
|
Use --page and --size flags to specify the page number and size.`),
|
||||||
To list pending tasks from "default" queue, run
|
Example: heredoc.Doc(`
|
||||||
asynq task ls --queue=default --state=pending
|
$ asynq task list --queue=myqueue --state=pending
|
||||||
|
$ asynq task list --queue=myqueue --state=aggregating --group=mygroup
|
||||||
To list the tasks from the second page, run
|
$ asynq task list --queue=myqueue --state=scheduled --page=2`),
|
||||||
asynq task ls --queue=default --state=pending --page=1
|
|
||||||
|
|
||||||
For aggregating tasks, additional --group flag is required.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
asynq task ls --queue=default --state=aggregating --group=mygroup
|
|
||||||
`,
|
|
||||||
Run: taskList,
|
Run: taskList,
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskInspectCmd = &cobra.Command{
|
var taskInspectCmd = &cobra.Command{
|
||||||
Use: "inspect --queue=QUEUE --id=TASK_ID",
|
Use: "inspect --queue=<queue> --id=<task_id>",
|
||||||
Short: "Display detailed information on the specified task",
|
Short: "Display detailed information on the specified task",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: taskInspect,
|
Run: taskInspect,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task inspect --queue=myqueue --id=f1720682-f5a6-4db1-8953-4f48ae541d0f`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskCancelCmd = &cobra.Command{
|
var taskCancelCmd = &cobra.Command{
|
||||||
Use: "cancel TASK_ID [TASK_ID...]",
|
Use: "cancel <task_id> [<task_id>...]",
|
||||||
Short: "Cancel one or more active tasks",
|
Short: "Cancel one or more active tasks",
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: taskCancel,
|
Run: taskCancel,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task cancel f1720682-f5a6-4db1-8953-4f48ae541d0f`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskArchiveCmd = &cobra.Command{
|
var taskArchiveCmd = &cobra.Command{
|
||||||
Use: "archive --queue=QUEUE --id=TASK_ID",
|
Use: "archive --queue=<queue> --id=<task_id>",
|
||||||
Short: "Archive a task with the given id",
|
Short: "Archive a task with the given id",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: taskArchive,
|
Run: taskArchive,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task archive --queue=myqueue --id=f1720682-f5a6-4db1-8953-4f48ae541d0f`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskDeleteCmd = &cobra.Command{
|
var taskDeleteCmd = &cobra.Command{
|
||||||
Use: "delete --queue=QUEUE --id=TASK_ID",
|
Use: "delete --queue=<queue> --id=<task_id>",
|
||||||
Short: "Delete a task with the given id",
|
Aliases: []string{"remove", "rm"},
|
||||||
Args: cobra.NoArgs,
|
Short: "Delete a task with the given id",
|
||||||
Run: taskDelete,
|
Args: cobra.NoArgs,
|
||||||
|
Run: taskDelete,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task delete --queue=myqueue --id=f1720682-f5a6-4db1-8953-4f48ae541d0f`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskRunCmd = &cobra.Command{
|
var taskRunCmd = &cobra.Command{
|
||||||
Use: "run --queue=QUEUE --id=TASK_ID",
|
Use: "run --queue=<queue> --id=<task_id>",
|
||||||
Short: "Run a task with the given id",
|
Short: "Run a task with the given id",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: taskRun,
|
Run: taskRun,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task run --queue=myqueue --id=f1720682-f5a6-4db1-8953-4f48ae541d0f`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskArchiveAllCmd = &cobra.Command{
|
var taskArchiveAllCmd = &cobra.Command{
|
||||||
Use: "archiveall --queue=QUEUE --state=STATE",
|
Use: "archiveall --queue=<queue> --state=<state>",
|
||||||
Short: "Archive all tasks in the given state",
|
Short: "Archive all tasks in the given state",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: taskArchiveAll,
|
Run: taskArchiveAll,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task archiveall --queue=myqueue --state=retry
|
||||||
|
$ asynq task archiveall --queue=myqueue --state=aggregating --group=mygroup`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskDeleteAllCmd = &cobra.Command{
|
var taskDeleteAllCmd = &cobra.Command{
|
||||||
Use: "deleteall --queue=QUEUE --state=STATE",
|
Use: "deleteall --queue=<queue> --state=<state>",
|
||||||
Short: "Delete all tasks in the given state",
|
Short: "Delete all tasks in the given state",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: taskDeleteAll,
|
Run: taskDeleteAll,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task deleteall --queue=myqueue --state=archived
|
||||||
|
$ asynq task deleteall --queue=myqueue --state=aggregating --group=mygroup`),
|
||||||
}
|
}
|
||||||
|
|
||||||
var taskRunAllCmd = &cobra.Command{
|
var taskRunAllCmd = &cobra.Command{
|
||||||
Use: "runall --queue=QUEUE --state=STATE",
|
Use: "runall --queue=<queue> --state=<state>",
|
||||||
Short: "Run all tasks in the given state",
|
Short: "Run all tasks in the given state",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
Run: taskRunAll,
|
Run: taskRunAll,
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
$ asynq task runall --queue=myqueue --state=retry
|
||||||
|
$ asynq task runall --queue=myqueue --state=aggregating --group=mygroup`),
|
||||||
}
|
}
|
||||||
|
|
||||||
func taskList(cmd *cobra.Command, args []string) {
|
func taskList(cmd *cobra.Command, args []string) {
|
||||||
@ -527,6 +542,17 @@ func taskArchiveAll(cmd *cobra.Command, args []string) {
|
|||||||
n, err = i.ArchiveAllScheduledTasks(qname)
|
n, err = i.ArchiveAllScheduledTasks(qname)
|
||||||
case "retry":
|
case "retry":
|
||||||
n, err = i.ArchiveAllRetryTasks(qname)
|
n, err = i.ArchiveAllRetryTasks(qname)
|
||||||
|
case "aggregating":
|
||||||
|
group, err := cmd.Flags().GetString("group")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if group == "" {
|
||||||
|
fmt.Println("error: Flag --group is required for aggregating tasks")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
n, err = i.ArchiveAllAggregatingTasks(qname, group)
|
||||||
default:
|
default:
|
||||||
fmt.Printf("error: unsupported state %q\n", state)
|
fmt.Printf("error: unsupported state %q\n", state)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -563,6 +589,17 @@ func taskDeleteAll(cmd *cobra.Command, args []string) {
|
|||||||
n, err = i.DeleteAllArchivedTasks(qname)
|
n, err = i.DeleteAllArchivedTasks(qname)
|
||||||
case "completed":
|
case "completed":
|
||||||
n, err = i.DeleteAllCompletedTasks(qname)
|
n, err = i.DeleteAllCompletedTasks(qname)
|
||||||
|
case "aggregating":
|
||||||
|
group, err := cmd.Flags().GetString("group")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if group == "" {
|
||||||
|
fmt.Println("error: Flag --group is required for aggregating tasks")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
n, err = i.DeleteAllAggregatingTasks(qname, group)
|
||||||
default:
|
default:
|
||||||
fmt.Printf("error: unsupported state %q\n", state)
|
fmt.Printf("error: unsupported state %q\n", state)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -595,6 +632,17 @@ func taskRunAll(cmd *cobra.Command, args []string) {
|
|||||||
n, err = i.RunAllRetryTasks(qname)
|
n, err = i.RunAllRetryTasks(qname)
|
||||||
case "archived":
|
case "archived":
|
||||||
n, err = i.RunAllArchivedTasks(qname)
|
n, err = i.RunAllArchivedTasks(qname)
|
||||||
|
case "aggregating":
|
||||||
|
group, err := cmd.Flags().GetString("group")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("error: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if group == "" {
|
||||||
|
fmt.Println("error: Flag --group is required for aggregating tasks")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
n, err = i.RunAllAggregatingTasks(qname, group)
|
||||||
default:
|
default:
|
||||||
fmt.Printf("error: unsupported state %q\n", state)
|
fmt.Printf("error: unsupported state %q\n", state)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
@ -3,13 +3,15 @@ module github.com/hibiken/asynq/tools
|
|||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/MakeNowJust/heredoc/v2 v2.0.1
|
||||||
github.com/fatih/color v1.9.0
|
github.com/fatih/color v1.9.0
|
||||||
github.com/go-redis/redis/v8 v8.11.4
|
github.com/go-redis/redis/v8 v8.11.4
|
||||||
github.com/hibiken/asynq v0.23.0
|
github.com/hibiken/asynq v0.23.0
|
||||||
github.com/hibiken/asynq/x v0.0.0-20220131170841-349f4c50fb1d
|
github.com/hibiken/asynq/x v0.0.0-20220131170841-349f4c50fb1d
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.11.0
|
||||||
github.com/spf13/afero v1.1.2 // indirect
|
|
||||||
github.com/spf13/cobra v1.1.1
|
github.com/spf13/cobra v1.1.1
|
||||||
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/spf13/viper v1.7.0
|
github.com/spf13/viper v1.7.0
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136
|
||||||
)
|
)
|
||||||
|
@ -14,6 +14,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
|
|||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
|
github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A=
|
||||||
|
github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM=
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
@ -140,8 +142,6 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m
|
|||||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
github.com/hibiken/asynq v0.19.0/go.mod h1:tyc63ojaW8SJ5SBm8mvI4DDONsguP5HE85EEl4Qr5Ig=
|
github.com/hibiken/asynq v0.19.0/go.mod h1:tyc63ojaW8SJ5SBm8mvI4DDONsguP5HE85EEl4Qr5Ig=
|
||||||
github.com/hibiken/asynq v0.21.0 h1:uH9XogJhjq/S39E0/DEPWLZQ6hHJ73UiblZTe4RzHwA=
|
|
||||||
github.com/hibiken/asynq v0.21.0/go.mod h1:tyc63ojaW8SJ5SBm8mvI4DDONsguP5HE85EEl4Qr5Ig=
|
|
||||||
github.com/hibiken/asynq v0.23.0 h1:kmKkNFgqiXBatC8oz94Mer6uvKoGn4STlIVDV5wnKyE=
|
github.com/hibiken/asynq v0.23.0 h1:kmKkNFgqiXBatC8oz94Mer6uvKoGn4STlIVDV5wnKyE=
|
||||||
github.com/hibiken/asynq v0.23.0/go.mod h1:K70jPVx+CAmmQrXot7Dru0D52EO7ob4BIun3ri5z1Qw=
|
github.com/hibiken/asynq v0.23.0/go.mod h1:K70jPVx+CAmmQrXot7Dru0D52EO7ob4BIun3ri5z1Qw=
|
||||||
github.com/hibiken/asynq/x v0.0.0-20220131170841-349f4c50fb1d h1:Er+U+9PmnyRHRDQjSjRQ24HoWvOY7w9Pk7bUPYM3Ags=
|
github.com/hibiken/asynq/x v0.0.0-20220131170841-349f4c50fb1d h1:Er+U+9PmnyRHRDQjSjRQ24HoWvOY7w9Pk7bUPYM3Ags=
|
||||||
@ -307,6 +307,7 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL
|
|||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136 h1:A1gGSx58LAGVHUUsOf7IiR0u8Xb6W51gRwfDBhkdcaw=
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
Loading…
Reference in New Issue
Block a user