diff --git a/cmd/tools/bench.go b/cmd/tools/bench.go index cb96c8d..067ee90 100644 --- a/cmd/tools/bench.go +++ b/cmd/tools/bench.go @@ -18,101 +18,108 @@ import ( log "github.com/sirupsen/logrus" ) -var benchCmd = &cobra.Command{ - Use: "bench", - Short: "Run a benchmark against a thalos node", - Run: func(cmd *cobra.Command, args []string) { - counter := 0 - interval, _ := cmd.Flags().GetDuration("interval") +func CreateBenchCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "bench", + Short: "Run a benchmark against a thalos node", + Run: func(cmd *cobra.Command, args []string) { + counter := 0 + interval, _ := cmd.Flags().GetDuration("interval") - url, _ := cmd.Flags().GetString("redis-url") - user, _ := cmd.Flags().GetString("redis-user") - pw, _ := cmd.Flags().GetString("redis-pw") - prefix, _ := cmd.Flags().GetString("prefix") - chain_id, _ := cmd.Flags().GetString("chain_id") - db, _ := cmd.Flags().GetInt("redis-db") + url, _ := cmd.Flags().GetString("redis-url") + user, _ := cmd.Flags().GetString("redis-user") + pw, _ := cmd.Flags().GetString("redis-pw") + prefix, _ := cmd.Flags().GetString("prefix") + chain_id, _ := cmd.Flags().GetString("chain_id") + db, _ := cmd.Flags().GetInt("redis-db") - log.WithFields(log.Fields{ - "url": url, - "prefix": prefix, - "chain_id": chain_id, - "database": db, - }).Info("Connecting to redis") + log.WithFields(log.Fields{ + "url": url, + "prefix": prefix, + "chain_id": chain_id, + "database": db, + }).Info("Connecting to redis") - // Create redis client - rdb := redis.NewClient(&redis.Options{ - Addr: url, - Username: user, - Password: pw, - DB: db, - }) + // Create redis client + rdb := redis.NewClient(&redis.Options{ + Addr: url, + Username: user, + Password: pw, + DB: db, + }) - if err := rdb.Ping(context.Background()).Err(); err != nil { - log.WithError(err).Fatal("Failed to connect to redis") - return - } + if err := rdb.Ping(context.Background()).Err(); err != nil { + log.WithError(err).Fatal("Failed to connect to redis") + return + } - log.Println("Connected to redis") + log.Println("Connected to redis") - log.WithFields(log.Fields{ - "interval": interval, - }).Info("Starting benchmark") + log.WithFields(log.Fields{ + "interval": interval, + }).Info("Starting benchmark") - sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{ - Prefix: prefix, - ChainID: chain_id, - }) + sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{ + Prefix: prefix, + ChainID: chain_id, + }) - codec, err := message.GetCodec("json") - if err != nil { - log.WithError(err).Fatal("Failed to get codec") - return - } + codec, err := message.GetCodec("json") + if err != nil { + log.WithError(err).Fatal("Failed to get codec") + return + } - client := api.NewClient(sub, codec.Decoder) + client := api.NewClient(sub, codec.Decoder) - // Subscribe to all actions - if err = client.Subscribe(api.ActionChannel{}.Channel()); err != nil { - log.WithError(err).Fatal("Failed to subscribe to channels") - return - } + // Subscribe to all actions + if err = client.Subscribe(api.ActionChannel{}.Channel()); err != nil { + log.WithError(err).Fatal("Failed to subscribe to channels") + return + } - go func() { - for t := range client.Channel() { - switch err := t.(type) { - case message.ActionTrace: - counter++ - case error: - log.WithError(err).Error("Error when reading stream") + go func() { + for t := range client.Channel() { + switch err := t.(type) { + case message.ActionTrace: + counter++ + case error: + log.WithError(err).Error("Error when reading stream") + } + } + }() + + t := time.Now() + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt) + + // Read stuff. + for { + select { + case <-sig: + fmt.Println("Got interrupt") + client.Close() + return + case now := <-time.After(interval): + elapsed := now.Sub(t) + t = now + + log.WithFields(log.Fields{ + "num_messages": counter, + "elapsed": elapsed, + "msg_per_sec": float64(counter) / elapsed.Seconds(), + "msg_per_ms": float64(counter) / float64(elapsed.Milliseconds()), + "msg_per_min": float64(counter) / elapsed.Minutes(), + }).Info("Benchmark results") + + counter = 0 } } - }() + }, + } - t := time.Now() - sig := make(chan os.Signal, 1) - signal.Notify(sig, os.Interrupt) + cmd.Flags().AddFlagSet(RedisFlags()) + cmd.Flags().DurationP("interval", "i", time.Minute, "How often the benchmark results should be displayed.") - // Read stuff. - for { - select { - case <-sig: - fmt.Println("Got interrupt") - client.Close() - return - case now := <-time.After(interval): - elapsed := now.Sub(t) - t = now - - log.WithFields(log.Fields{ - "num_messages": counter, - "elapsed": elapsed, - "msg_per_sec": float64(counter) / elapsed.Seconds(), - "msg_per_ms": float64(counter) / float64(elapsed.Milliseconds()), - "msg_per_min": float64(counter) / elapsed.Minutes(), - }).Info("Benchmark results") - - counter = 0 - } - } - }, + return cmd } diff --git a/cmd/tools/flags.go b/cmd/tools/flags.go new file mode 100644 index 0000000..fd54332 --- /dev/null +++ b/cmd/tools/flags.go @@ -0,0 +1,14 @@ +package main + +import "github.com/spf13/pflag" + +func RedisFlags() *pflag.FlagSet { + set := pflag.FlagSet{} + set.String("redis-url", "127.0.0.1:6379", "host:port to the redis server") + set.String("redis-user", "", "User to use when authenticating to the server") + set.String("redis-pw", "", "Password to use when authenticating to the server") + set.Int("redis-db", 0, "What redis database we should connect to.") + set.String("prefix", "ship", "redis prefix") + set.String("chain_id", "1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4", "chain id") + return &set +} diff --git a/cmd/tools/main.go b/cmd/tools/main.go index abb206d..3e131ac 100644 --- a/cmd/tools/main.go +++ b/cmd/tools/main.go @@ -1,28 +1,15 @@ package main import ( - "time" - _ "github.com/eosswedenorg/thalos/internal/log" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/spf13/pflag" ) var VersionString string = "dev" -var rootCmd *cobra.Command - -func init() { - redisFlags := pflag.FlagSet{} - redisFlags.String("redis-url", "127.0.0.1:6379", "host:port to the redis server") - redisFlags.String("redis-user", "", "User to use when authenticating to the server") - redisFlags.String("redis-pw", "", "Password to use when authenticating to the server") - redisFlags.Int("redis-db", 0, "What redis database we should connect to.") - redisFlags.String("prefix", "ship", "redis prefix") - redisFlags.String("chain_id", "1064487b3cd1a897ce03ae5b6a865651747e2e152090f99c1d19d44e01aea5a4", "chain id") - - rootCmd = &cobra.Command{ +func main() { + rootCmd := &cobra.Command{ Use: "thalos-tools", Short: "Collection of tools for dealing with the thalos application", FParseErrWhitelist: cobra.FParseErrWhitelist{ @@ -31,33 +18,13 @@ func init() { Version: VersionString, } - benchCmd.Flags().AddFlagSet(&redisFlags) - benchCmd.Flags().DurationP("interval", "i", time.Minute, "How often the benchmark results should be displayed.") - - validateCmd.Flags().AddFlagSet(&redisFlags) - - MockPublisherCmd.Flags().AddFlagSet(&redisFlags) - MockPublisherCmd.Flags().String("codec", "json", "codec to use") - - RedisACLCmd.Flags().String("default-pw", "", "Password to use for the default account, if not provided a random one will be generated") - RedisACLCmd.Flags().String("client", "thalos-client", "Thalos client account name") - RedisACLCmd.Flags().String("client-pw", "", "Password to use for the thalos client account, if not provided a random one will be generated") - RedisACLCmd.Flags().String("server", "thalos", "Thalos account name") - RedisACLCmd.Flags().String("server-pw", "", "Password to use for the thalos server account, if not provided a random one will be generated") - RedisACLCmd.Flags().String("prefix", "ship", "Redis key prefix") - RedisACLCmd.Flags().Bool("cleartext", false, "If passwords should be hashed or left in cleartext.") - RedisACLCmd.Flags().String("file", "", "Where the config should be written to (default: standard out)") - RedisACLCmd.Flags().Uint("pass-len", 32, "The length of generated passwords") - rootCmd.AddCommand( - validateCmd, - benchCmd, - RedisACLCmd, - MockPublisherCmd, + CreateValidateCmd(), + CreateBenchCmd(), + CreateRedisACLCmd(), + CreateMockPublisherCmd(), ) -} -func main() { if err := rootCmd.Execute(); err != nil { log.Fatal(err) } diff --git a/cmd/tools/mock_publisher.go b/cmd/tools/mock_publisher.go index ec38871..6a9e028 100644 --- a/cmd/tools/mock_publisher.go +++ b/cmd/tools/mock_publisher.go @@ -16,100 +16,106 @@ import ( log "github.com/sirupsen/logrus" ) -var MockPublisherCmd = &cobra.Command{ - Use: "mock_publisher", - Short: "Run a publisher that mocks messages to a redis server. tries to send as many messages as possible", - Run: func(cmd *cobra.Command, args []string) { - url, _ := cmd.Flags().GetString("redis-url") - user, _ := cmd.Flags().GetString("redis-user") - pw, _ := cmd.Flags().GetString("redis-pw") - prefix, _ := cmd.Flags().GetString("prefix") - chain_id, _ := cmd.Flags().GetString("chain_id") - db, _ := cmd.Flags().GetInt("redis-db") +func CreateMockPublisherCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "mock_publisher", + Short: "Run a publisher that mocks messages to a redis server. tries to send as many messages as possible", + Run: func(cmd *cobra.Command, args []string) { + url, _ := cmd.Flags().GetString("redis-url") + user, _ := cmd.Flags().GetString("redis-user") + pw, _ := cmd.Flags().GetString("redis-pw") + prefix, _ := cmd.Flags().GetString("prefix") + chain_id, _ := cmd.Flags().GetString("chain_id") + db, _ := cmd.Flags().GetInt("redis-db") - // Create redis client - rdb := redis.NewClient(&redis.Options{ - Addr: url, - Username: user, - Password: pw, - DB: db, - }) + // Create redis client + rdb := redis.NewClient(&redis.Options{ + Addr: url, + Username: user, + Password: pw, + DB: db, + }) - codecArg, _ := cmd.Flags().GetString("codec") + codecArg, _ := cmd.Flags().GetString("codec") - codec, err := message.GetCodec(codecArg) - if err != nil { - log.WithError(err).Fatal("Failed to get codec") - return - } + codec, err := message.GetCodec(codecArg) + if err != nil { + log.WithError(err).Fatal("Failed to get codec") + return + } - log.WithFields(log.Fields{ - "url": url, - "prefix": prefix, - "chain_id": chain_id, - "database": db, - }).Info("Starting mock publisher") + log.WithFields(log.Fields{ + "url": url, + "prefix": prefix, + "chain_id": chain_id, + "database": db, + }).Info("Starting mock publisher") - ns := api_redis.Namespace{ - Prefix: prefix, - ChainID: chain_id, - } - publisher := redis_driver.NewPublisher(context.Background(), rdb, ns) + ns := api_redis.Namespace{ + Prefix: prefix, + ChainID: chain_id, + } + publisher := redis_driver.NewPublisher(context.Background(), rdb, ns) - msg := message.ActionTrace{ - TxID: "401e8a7e5deb18a2a69fc6559f49509a155f4355c85efb69c1c1fab5b60ee532", - BlockNum: 18237917, - Timestamp: time.Date(2014, 3, 22, 11, 36, 43, 0, time.UTC), - Receipt: &message.ActionReceipt{ - Receiver: "acc1", - ActDigest: "4c5c08be612e937564fc526ebb5fadf34ae8c2a571fe9d7cdb3ffcdfc53b0e8d", - GlobalSequence: 12314, - RecvSequence: 237187239, - AuthSequence: []message.AccountAuthSequence{ + msg := message.ActionTrace{ + TxID: "401e8a7e5deb18a2a69fc6559f49509a155f4355c85efb69c1c1fab5b60ee532", + BlockNum: 18237917, + Timestamp: time.Date(2014, 3, 22, 11, 36, 43, 0, time.UTC), + Receipt: &message.ActionReceipt{ + Receiver: "acc1", + ActDigest: "4c5c08be612e937564fc526ebb5fadf34ae8c2a571fe9d7cdb3ffcdfc53b0e8d", + GlobalSequence: 12314, + RecvSequence: 237187239, + AuthSequence: []message.AccountAuthSequence{ + { + Account: "acc1", + Sequence: 2732863, + }, + { + Account: "acc2", + Sequence: 263762, + }, + }, + CodeSequence: 2327832, + ABISequence: 12376189, + }, + Name: "fake", + Contract: "fake", + Receiver: "acc1", + Data: map[string]interface{}{ + "one": 238771832, + "two": "str", + }, + Authorization: []message.PermissionLevel{ { - Account: "acc1", - Sequence: 2732863, + Actor: "acc1", + Permission: "active", }, { - Account: "acc2", - Sequence: 263762, + Actor: "acc2", + Permission: "owner", }, }, - CodeSequence: 2327832, - ABISequence: 12376189, - }, - Name: "fake", - Contract: "fake", - Receiver: "acc1", - Data: map[string]interface{}{ - "one": 238771832, - "two": "str", - }, - Authorization: []message.PermissionLevel{ - { - Actor: "acc1", - Permission: "active", - }, - { - Actor: "acc2", - Permission: "owner", - }, - }, - Except: "err", - Error: 2, - Return: []byte{0xbe, 0xef}, - } + Except: "err", + Error: 2, + Return: []byte{0xbe, 0xef}, + } - payload, err := codec.Encoder(msg) - if err != nil { - log.WithError(err).Fatal("Failed to encode message") - return - } - channel := api.ActionChannel{}.Channel() + payload, err := codec.Encoder(msg) + if err != nil { + log.WithError(err).Fatal("Failed to encode message") + return + } + channel := api.ActionChannel{}.Channel() - for { - _ = publisher.Write(channel, payload) - publisher.Flush() - } - }, + for { + _ = publisher.Write(channel, payload) + publisher.Flush() + } + }, + } + + cmd.Flags().AddFlagSet(RedisFlags()) + cmd.Flags().String("codec", "json", "codec to use") + return cmd } diff --git a/cmd/tools/redis-acl.go b/cmd/tools/redis-acl.go index 0f4496c..ad15036 100644 --- a/cmd/tools/redis-acl.go +++ b/cmd/tools/redis-acl.go @@ -43,7 +43,6 @@ func NewUser(name, password string, pass_len uint) User { } func (u *User) GetPassword() string { - if u.Hash { return "#" + hash(u.Password) } @@ -99,60 +98,74 @@ user {{.client}} on {{.clientpw}} resetchannels &{{.prefix}}::* -@all +subscribe }) } -var RedisACLCmd = &cobra.Command{ - Use: "redis-acl", - Short: "create a users.acl file", - Run: func(cmd *cobra.Command, args []string) { - var err error - out := os.Stdout +func CreateRedisACLCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "redis-acl", + Short: "create a users.acl file", + Run: func(cmd *cobra.Command, args []string) { + var err error + out := os.Stdout - rnd = rand.New(rand.NewSource(time.Now().UnixNano())) + rnd = rand.New(rand.NewSource(time.Now().UnixNano())) - flagDefUserPw, _ := cmd.Flags().GetString("default-pw") - flagServer, _ := cmd.Flags().GetString("server") - flagServerPw, _ := cmd.Flags().GetString("server-pw") - flagClient, _ := cmd.Flags().GetString("client") - flagClientPw, _ := cmd.Flags().GetString("client-pw") - flagPrefix, _ := cmd.Flags().GetString("prefix") - flagPassLen, _ := cmd.Flags().GetUint("pass-len") + flagDefUserPw, _ := cmd.Flags().GetString("default-pw") + flagServer, _ := cmd.Flags().GetString("server") + flagServerPw, _ := cmd.Flags().GetString("server-pw") + flagClient, _ := cmd.Flags().GetString("client") + flagClientPw, _ := cmd.Flags().GetString("client-pw") + flagPrefix, _ := cmd.Flags().GetString("prefix") + flagPassLen, _ := cmd.Flags().GetUint("pass-len") - defaultUser := NewUser("default", flagDefUserPw, flagPassLen) - serverUser := NewUser(flagServer, flagServerPw, flagPassLen) - clientUser := NewUser(flagClient, flagClientPw, flagPassLen) + defaultUser := NewUser("default", flagDefUserPw, flagPassLen) + serverUser := NewUser(flagServer, flagServerPw, flagPassLen) + clientUser := NewUser(flagClient, flagClientPw, flagPassLen) - atleastOneGeneratedPw := defaultUser.Generated || serverUser.Generated || clientUser.Generated + atleastOneGeneratedPw := defaultUser.Generated || serverUser.Generated || clientUser.Generated - cleartext, _ := cmd.Flags().GetBool("cleartext") - if !cleartext { - if atleastOneGeneratedPw { - println("Passwords") + cleartext, _ := cmd.Flags().GetBool("cleartext") + if !cleartext { + if atleastOneGeneratedPw { + println("Passwords") + } + + defaultUser.PrintIfGeneratedPW() + serverUser.PrintIfGeneratedPW() + clientUser.PrintIfGeneratedPW() + + defaultUser.Hash = true + serverUser.Hash = true + clientUser.Hash = true } - defaultUser.PrintIfGeneratedPW() - serverUser.PrintIfGeneratedPW() - clientUser.PrintIfGeneratedPW() + filename, _ := cmd.Flags().GetString("file") + if len(filename) > 0 { + out, err = os.Create(filename) + if err != nil { + log.WithError(err).Fatal("Failed to create output file") + return + } + defer out.Close() + } else if !cleartext && atleastOneGeneratedPw { + fmt.Println() + } - defaultUser.Hash = true - serverUser.Hash = true - clientUser.Hash = true - } - - filename, _ := cmd.Flags().GetString("file") - if len(filename) > 0 { - out, err = os.Create(filename) + err = writeTemplate(out, defaultUser, serverUser, clientUser, flagPrefix) if err != nil { - log.WithError(err).Fatal("Failed to create output file") + log.WithError(err).Fatal("Failed to writte config") return } - defer out.Close() - } else if !cleartext && atleastOneGeneratedPw { - fmt.Println() - } + }, + } - err = writeTemplate(out, defaultUser, serverUser, clientUser, flagPrefix) - if err != nil { - log.WithError(err).Fatal("Failed to writte config") - return - } - }, + cmd.Flags().String("default-pw", "", "Password to use for the default account, if not provided a random one will be generated") + cmd.Flags().String("client", "thalos-client", "Thalos client account name") + cmd.Flags().String("client-pw", "", "Password to use for the thalos client account, if not provided a random one will be generated") + cmd.Flags().String("server", "thalos", "Thalos account name") + cmd.Flags().String("server-pw", "", "Password to use for the thalos server account, if not provided a random one will be generated") + cmd.Flags().String("prefix", "ship", "Redis key prefix") + cmd.Flags().Bool("cleartext", false, "If passwords should be hashed or left in cleartext.") + cmd.Flags().String("file", "", "Where the config should be written to (default: standard out)") + cmd.Flags().Uint("pass-len", 32, "The length of generated passwords") + + return cmd } diff --git a/cmd/tools/validate.go b/cmd/tools/validate.go index 5c040b6..310c8c1 100644 --- a/cmd/tools/validate.go +++ b/cmd/tools/validate.go @@ -18,101 +18,107 @@ import ( log "github.com/sirupsen/logrus" ) -var validateCmd = &cobra.Command{ - Use: "validate", - Short: "Validate a thalos server by following action traces and makes sure that blocks arrive in order.", - Run: func(cmd *cobra.Command, args []string) { - status_duration := time.Second * 10 +func CreateValidateCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "validate", + Short: "Validate a thalos server by following action traces and makes sure that blocks arrive in order.", + Run: func(cmd *cobra.Command, args []string) { + status_duration := time.Second * 10 - url, _ := cmd.Flags().GetString("redis-url") - prefix, _ := cmd.Flags().GetString("prefix") - chain_id, _ := cmd.Flags().GetString("chain_id") - db, _ := cmd.Flags().GetInt("redis-db") + url, _ := cmd.Flags().GetString("redis-url") + prefix, _ := cmd.Flags().GetString("prefix") + chain_id, _ := cmd.Flags().GetString("chain_id") + db, _ := cmd.Flags().GetInt("redis-db") - log.WithFields(log.Fields{ - "url": url, - "prefix": prefix, - "chain_id": chain_id, - "database": db, - }).Info("Connecting to redis") + log.WithFields(log.Fields{ + "url": url, + "prefix": prefix, + "chain_id": chain_id, + "database": db, + }).Info("Connecting to redis") - // Create redis client - rdb := redis.NewClient(&redis.Options{ - Addr: url, - DB: db, - }) + // Create redis client + rdb := redis.NewClient(&redis.Options{ + Addr: url, + DB: db, + }) - if err := rdb.Ping(context.Background()).Err(); err != nil { - log.WithError(err).Fatal("Failed to connect to redis") - return - } + if err := rdb.Ping(context.Background()).Err(); err != nil { + log.WithError(err).Fatal("Failed to connect to redis") + return + } - log.Println("Connected to redis") + log.Println("Connected to redis") - log.Info("Starting validation, following the stream") + log.Info("Starting validation, following the stream") - sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{ - Prefix: prefix, - ChainID: chain_id, - }) + sub := api_redis.NewSubscriber(context.Background(), rdb, api_redis.Namespace{ + Prefix: prefix, + ChainID: chain_id, + }) - codec, err := message.GetCodec("json") - if err != nil { - log.WithError(err).Fatal("Failed to get codec") - return - } + codec, err := message.GetCodec("json") + if err != nil { + log.WithError(err).Fatal("Failed to get codec") + return + } - client := api.NewClient(sub, codec.Decoder) + client := api.NewClient(sub, codec.Decoder) - // Subscribe to all actions - if err = client.Subscribe(api.ActionChannel{}.Channel()); err != nil { - log.WithError(err).Fatal("Failed to subscribe to channels") - return - } + // Subscribe to all actions + if err = client.Subscribe(api.ActionChannel{}.Channel()); err != nil { + log.WithError(err).Fatal("Failed to subscribe to channels") + return + } - block_num := uint32(0) - timeout := time.Second * 5 - timer := time.NewTicker(timeout) + block_num := uint32(0) + timeout := time.Second * 5 + timer := time.NewTicker(timeout) - go func() { - for t := range client.Channel() { - switch msg := t.(type) { - case error: - log.WithError(msg).Error("Error when reading stream") - case message.ActionTrace: - if block_num > 0 { - diff := int32(msg.BlockNum - block_num) - if diff < 0 || diff > 1 { - log.WithFields(log.Fields{ - "current_block": block_num, - "block": msg.BlockNum, - "diff": diff, - }).Warn("Invalid") + go func() { + for t := range client.Channel() { + switch msg := t.(type) { + case error: + log.WithError(msg).Error("Error when reading stream") + case message.ActionTrace: + if block_num > 0 { + diff := int32(msg.BlockNum - block_num) + if diff < 0 || diff > 1 { + log.WithFields(log.Fields{ + "current_block": block_num, + "block": msg.BlockNum, + "diff": diff, + }).Warn("Invalid") + } } + block_num = msg.BlockNum + timer.Reset(timeout) } - block_num = msg.BlockNum - timer.Reset(timeout) + } + }() + + sig := make(chan os.Signal, 1) + signal.Notify(sig, os.Interrupt) + + for { + select { + case <-sig: + fmt.Println("Got interrupt") + client.Close() + return + case <-timer.C: + log.WithField("duration", timeout). + Warn("Did not get any messages during the defined duration") + case <-time.After(status_duration): + log.WithFields(log.Fields{ + "current_block": block_num, + }).Info("Status") } } - }() + }, + } - sig := make(chan os.Signal, 1) - signal.Notify(sig, os.Interrupt) + cmd.Flags().AddFlagSet(RedisFlags()) - for { - select { - case <-sig: - fmt.Println("Got interrupt") - client.Close() - return - case <-timer.C: - log.WithField("duration", timeout). - Warn("Did not get any messages during the defined duration") - case <-time.After(status_duration): - log.WithFields(log.Fields{ - "current_block": block_num, - }).Info("Status") - } - } - }, + return cmd }