From 463cd4755a64c45471a522eee873e569891d7be7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:30:21 +0000 Subject: [PATCH 1/7] Initial plan From 500d30f16c86872e45d2b33d8efcd1bc476b8c96 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:43:59 +0000 Subject: [PATCH 2/7] Add queue_max and queue_usage to /api/stat/app endpoint Co-authored-by: appleboy <21979+appleboy@users.noreply.github.com> --- router/server.go | 12 ++++++++++-- router/server_test.go | 9 +++++++-- status/status.go | 2 ++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/router/server.go b/router/server.go index 5e3673daa..4eebb63e9 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 = int64(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 be99c964a..24b20f5cc 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, queueUsage, int64(0)) }) } diff --git a/status/status.go b/status/status.go index 9dc5d3ce8..9e5bfdfdb 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 int64 `json:"queue_usage"` BusyWorkers int64 `json:"busy_workers"` SuccessTasks uint64 `json:"success_tasks"` FailureTasks uint64 `json:"failure_tasks"` From 5f319b0b53eed3a16f95ead5634ccf93e103050d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:47:33 +0000 Subject: [PATCH 3/7] Fix potential integer overflow in queue_usage calculation Co-authored-by: appleboy <21979+appleboy@users.noreply.github.com> --- router/server.go | 2 +- router/server_test.go | 2 +- status/status.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/router/server.go b/router/server.go index 4eebb63e9..eba1eb048 100644 --- a/router/server.go +++ b/router/server.go @@ -125,7 +125,7 @@ func appStatusHandler(cfg *config.ConfYaml, q *queue.Queue) gin.HandlerFunc { // Calculate queue usage as pending tasks (submitted - completed) completedTasks := q.SuccessTasks() + q.FailureTasks() if q.SubmittedTasks() >= completedTasks { - result.QueueUsage = int64(q.SubmittedTasks() - completedTasks) + result.QueueUsage = q.SubmittedTasks() - completedTasks } else { result.QueueUsage = 0 } diff --git a/router/server_test.go b/router/server_test.go index 24b20f5cc..84c6ede4b 100644 --- a/router/server_test.go +++ b/router/server_test.go @@ -278,7 +278,7 @@ func TestAPIStatusAppHandler(t *testing.T) { assert.Equal(t, http.StatusOK, r.Code) assert.Equal(t, cfg.Core.QueueNum, queueMax) assert.Nil(t, err) - assert.GreaterOrEqual(t, queueUsage, int64(0)) + assert.GreaterOrEqual(t, uint64(queueUsage), uint64(0)) }) } diff --git a/status/status.go b/status/status.go index 9e5bfdfdb..9231bf941 100644 --- a/status/status.go +++ b/status/status.go @@ -26,7 +26,7 @@ var StatStorage *StateStorage type App struct { Version string `json:"version"` QueueMax int64 `json:"queue_max"` - QueueUsage int64 `json:"queue_usage"` + QueueUsage uint64 `json:"queue_usage"` BusyWorkers int64 `json:"busy_workers"` SuccessTasks uint64 `json:"success_tasks"` FailureTasks uint64 `json:"failure_tasks"` From 04dd7bb67eb3abfd8536e43d6f5a99c4a3620476 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:51:20 +0000 Subject: [PATCH 4/7] Update README documentation with queue_max and queue_usage fields Co-authored-by: appleboy <21979+appleboy@users.noreply.github.com> --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e82a069c1..7aa323d46 100644 --- a/README.md +++ b/README.md @@ -521,6 +521,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, From 37e4c47f228b845b8a6d63518874f9bab6dc30bd Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 22:51:16 +0800 Subject: [PATCH 5/7] fix(queue): add Redis database selection support for queue.redis configuration (#849) * Initial plan * Add Redis DB configuration support for queue.redis - Add db field to SectionRedisQueue configuration structure - Update default configuration with queue.redis.db setting (default: 0) - Update config loading to read queue.redis.db parameter - Pass db parameter to redisdb.NewWorker in main.go using WithDB option - Add comprehensive tests for Redis DB configuration - Update test configuration files with db field Co-authored-by: appleboy <21979+appleboy@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: appleboy <21979+appleboy@users.noreply.github.com> --- config/config.go | 3 +++ config/config_test.go | 38 +++++++++++++++++++++++++++++ config/testdata/config.yml | 1 + config/testdata/redis_db_config.yml | 20 +++++++++++++++ main.go | 1 + 5 files changed, 63 insertions(+) create mode 100644 config/testdata/redis_db_config.yml diff --git a/config/config.go b/config/config.go index 132973f0c..e84e9b393 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 497a8a928..1867e09a7 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 b8fd5f7cc..4bbfa385c 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 000000000..10d95f720 --- /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 40cc6c5a3..b8c1f8139 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), From 5d704c743caa8e656ba6bc7990146506b7ee2e5a Mon Sep 17 00:00:00 2001 From: appleboy Date: Wed, 29 Oct 2025 22:53:26 +0800 Subject: [PATCH 6/7] docs(readme): refactor and enhance redis configuration options - Remove duplicate redis configuration block - Add db option to redis configuration Signed-off-by: appleboy --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 7aa323d46..a77402537 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 From 414262c1cbf056e728bb06bd42977f4170b42685 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:30:21 +0000 Subject: [PATCH 7/7] Initial plan