diff --git a/README.md b/README.md index e82a069c..a7740253 100644 --- a/README.md +++ b/README.md @@ -177,11 +177,6 @@ queue: addr: 127.0.0.1:4222 subj: gorush queue: gorush - redis: - addr: 127.0.0.1:6379 - group: gorush - consumer: gorush - stream_name: gorush redis: addr: 127.0.0.1:6379 group: gorush @@ -190,6 +185,7 @@ queue: with_tls: false username: "" password: "" + db: 0 ios: enabled: false @@ -521,6 +517,8 @@ Show success or failure counts information of notification. ```json { "version": "v1.6.2", + "queue_max": 8192, + "queue_usage": 0, "busy_workers": 0, "success_tasks": 32, "failure_tasks": 49, diff --git a/config/config.go b/config/config.go index 132973f0..e84e9b39 100644 --- a/config/config.go +++ b/config/config.go @@ -88,6 +88,7 @@ queue: with_tls: false username: "" password: "" + db: 0 ios: enabled: false @@ -263,6 +264,7 @@ type SectionRedisQueue struct { Addr string `yaml:"addr"` Username string `yaml:"username"` Password string `yaml:"password"` + DB int `yaml:"db"` StreamName string `yaml:"stream_name"` Group string `yaml:"group"` Consumer string `yaml:"consumer"` @@ -487,6 +489,7 @@ func loadConfigFromViper() (*ConfYaml, error) { conf.Queue.Redis.WithTLS = viper.GetBool("queue.redis.with_tls") conf.Queue.Redis.Username = viper.GetString("queue.redis.username") conf.Queue.Redis.Password = viper.GetString("queue.redis.password") + conf.Queue.Redis.DB = viper.GetInt("queue.redis.db") // Stat Engine conf.Stat.Engine = viper.GetString("stat.engine") diff --git a/config/config_test.go b/config/config_test.go index 497a8a92..1867e09a 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -160,6 +160,7 @@ func (suite *ConfigTestSuite) TestValidateConfDefault() { assert.Equal(suite.T(), "", suite.ConfGorushDefault.Queue.Redis.Username) assert.Equal(suite.T(), "", suite.ConfGorushDefault.Queue.Redis.Password) assert.Equal(suite.T(), false, suite.ConfGorushDefault.Queue.Redis.WithTLS) + assert.Equal(suite.T(), 0, suite.ConfGorushDefault.Queue.Redis.DB) // log assert.Equal(suite.T(), "string", suite.ConfGorushDefault.Log.Format) @@ -299,6 +300,43 @@ func TestLoadConfigFromEnv(t *testing.T) { assert.Equal(t, "x-auth-key:0987654321", ConfGorush.Core.FeedbackHeader[1]) } +func TestRedisDBConfiguration(t *testing.T) { + // Test loading Redis DB configuration from file + conf, err := LoadConf("testdata/redis_db_config.yml") + if err != nil { + t.Fatalf("failed to load redis_db_config.yml: %v", err) + } + + // Test queue.redis.db is properly loaded + assert.Equal(t, "redis", conf.Queue.Engine) + assert.Equal(t, 5, conf.Queue.Redis.DB) + + // Test stat.redis.db is properly loaded + assert.Equal(t, "redis", conf.Stat.Engine) + assert.Equal(t, 3, conf.Stat.Redis.DB) +} + +func TestRedisDBConfigurationFromEnv(t *testing.T) { + // Test loading Redis DB configuration from environment variables + os.Setenv("GORUSH_QUEUE_REDIS_DB", "7") + os.Setenv("GORUSH_STAT_REDIS_DB", "9") + + conf, err := LoadConf() + if err != nil { + t.Fatalf("failed to load config: %v", err) + } + + // Test queue.redis.db is properly loaded from env + assert.Equal(t, 7, conf.Queue.Redis.DB) + + // Test stat.redis.db is properly loaded from env + assert.Equal(t, 9, conf.Stat.Redis.DB) + + // Clean up + os.Unsetenv("GORUSH_QUEUE_REDIS_DB") + os.Unsetenv("GORUSH_STAT_REDIS_DB") +} + func TestLoadWrongDefaultYAMLConfig(t *testing.T) { defaultConf = []byte(`a`) _, err := LoadConf() diff --git a/config/testdata/config.yml b/config/testdata/config.yml index b8fd5f7c..4bbfa385 100644 --- a/config/testdata/config.yml +++ b/config/testdata/config.yml @@ -73,6 +73,7 @@ queue: username: "" password: "" with_tls: false + db: 0 ios: enabled: false diff --git a/config/testdata/redis_db_config.yml b/config/testdata/redis_db_config.yml new file mode 100644 index 00000000..10d95f72 --- /dev/null +++ b/config/testdata/redis_db_config.yml @@ -0,0 +1,20 @@ +queue: + engine: "redis" + redis: + addr: 127.0.0.1:6379 + group: gorush + consumer: gorush + stream_name: gorush + username: "" + password: "" + with_tls: false + db: 5 + +stat: + engine: "redis" + redis: + cluster: false + addr: "localhost:6379" + username: "" + password: "" + db: 3 diff --git a/main.go b/main.go index 40cc6c5a..b8c1f813 100644 --- a/main.go +++ b/main.go @@ -344,6 +344,7 @@ func main() { redisdb.WithAddr(cfg.Queue.Redis.Addr), redisdb.WithUsername(cfg.Queue.Redis.Username), redisdb.WithPassword(cfg.Queue.Redis.Password), + redisdb.WithDB(cfg.Queue.Redis.DB), redisdb.WithStreamName(cfg.Queue.Redis.StreamName), redisdb.WithGroup(cfg.Queue.Redis.Group), redisdb.WithConsumer(cfg.Queue.Redis.Consumer), diff --git a/router/server.go b/router/server.go index 5e3673da..eba1eb04 100644 --- a/router/server.go +++ b/router/server.go @@ -116,11 +116,19 @@ func metricsHandler(c *gin.Context) { promhttp.Handler().ServeHTTP(c.Writer, c.Request) } -func appStatusHandler(q *queue.Queue) gin.HandlerFunc { +func appStatusHandler(cfg *config.ConfYaml, q *queue.Queue) gin.HandlerFunc { return func(c *gin.Context) { result := status.App{} result.Version = GetVersion() + result.QueueMax = cfg.Core.QueueNum + // Calculate queue usage as pending tasks (submitted - completed) + completedTasks := q.SuccessTasks() + q.FailureTasks() + if q.SubmittedTasks() >= completedTasks { + result.QueueUsage = q.SubmittedTasks() - completedTasks + } else { + result.QueueUsage = 0 + } result.BusyWorkers = q.BusyWorkers() result.SuccessTasks = q.SuccessTasks() result.FailureTasks = q.FailureTasks() @@ -209,7 +217,7 @@ func routerEngine(cfg *config.ConfYaml, q *queue.Queue) *gin.Engine { r.Use(StatMiddleware()) r.GET(cfg.API.StatGoURI, api.GinHandler) - r.GET(cfg.API.StatAppURI, appStatusHandler(q)) + r.GET(cfg.API.StatAppURI, appStatusHandler(cfg, q)) r.GET(cfg.API.ConfigURI, configHandler(cfg)) r.GET(cfg.API.SysStatURI, sysStatsHandler()) r.POST(cfg.API.PushURI, pushHandler(cfg, q)) diff --git a/router/server_test.go b/router/server_test.go index be99c964..84c6ede4 100644 --- a/router/server_test.go +++ b/router/server_test.go @@ -270,10 +270,15 @@ func TestAPIStatusAppHandler(t *testing.T) { Run(routerEngine(cfg, q), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) { data := r.Body.Bytes() - value, _ := jsonparser.GetString(data, "version") + version, _ := jsonparser.GetString(data, "version") + queueMax, _ := jsonparser.GetInt(data, "queue_max") + queueUsage, err := jsonparser.GetInt(data, "queue_usage") - assert.Equal(t, appVersion, value) + assert.Equal(t, appVersion, version) assert.Equal(t, http.StatusOK, r.Code) + assert.Equal(t, cfg.Core.QueueNum, queueMax) + assert.Nil(t, err) + assert.GreaterOrEqual(t, uint64(queueUsage), uint64(0)) }) } diff --git a/status/status.go b/status/status.go index 9dc5d3ce..9231bf94 100644 --- a/status/status.go +++ b/status/status.go @@ -25,6 +25,8 @@ var StatStorage *StateStorage // App is status structure type App struct { Version string `json:"version"` + QueueMax int64 `json:"queue_max"` + QueueUsage uint64 `json:"queue_usage"` BusyWorkers int64 `json:"busy_workers"` SuccessTasks uint64 `json:"success_tasks"` FailureTasks uint64 `json:"failure_tasks"`