From 7f9cc1e435a497a88fa4c764af64f77cfae8d6af Mon Sep 17 00:00:00 2001 From: zhangwenjian Date: Sat, 5 Sep 2026 23:01:27 +0800 Subject: [PATCH 1/2] =?UTF-8?q?test=E2=9C=85:=20a=20configuration=20reload?= =?UTF-8?q?=20installs=20a=20new=20queue=20for=20the=20consumers=20to=20no?= =?UTF-8?q?tice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #892 is that a reload replaces the queue adapter and the consumers registered against the previous one are left attached to a queue nobody publishes to any more. The fix has two halves and only one of them was covered. attachQueueConsumers gives a new queue its own consumers and the same queue none, which cmd/api tests against a queue it controls by passing generation numbers in by hand. What nothing asserted is that a reload actually produces a new generation for it to notice - the half that lives in this package. Setup is what config re-runs on every change, so calling it twice is what a reload does here. The generation goes 0, 1, 2. The counter-proof compiles and fails: dropping the increment in setupQueue reports that the first Setup installed no queue at all, because a generation that never moves is indistinguishable from never having been set. This closes the loop rather than adding coverage for its own sake: with both halves asserted, the claim that #892 is fixed rests on tests instead of on reading the two functions and believing they meet. --- common/storage/setup_gen_test.go | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 common/storage/setup_gen_test.go diff --git a/common/storage/setup_gen_test.go b/common/storage/setup_gen_test.go new file mode 100644 index 00000000..d1c455ac --- /dev/null +++ b/common/storage/setup_gen_test.go @@ -0,0 +1,38 @@ +package storage + +import ( + "testing" + + "github.com/go-admin-team/go-admin-core/v2/sdk/config" +) + +// Issue #892: a configuration reload replaces the queue adapter and the +// consumers registered against the previous one are attached to a queue nobody +// publishes to any more. +// +// The fix has two halves. attachQueueConsumers gives a new queue its own +// consumers and the same queue none, which cmd/api covers against a queue the +// test controls. This is the other half: that a reload actually produces a new +// queue for it to notice. Setup is what config re-runs on every change, so +// calling it twice is what a reload does to this package. +func TestSetupBumpsTheQueueGenerationOnEveryReload(t *testing.T) { + prevQ, prevC := config.QueueConfig, config.CacheConfig + t.Cleanup(func() { config.QueueConfig, config.CacheConfig = prevQ, prevC }) + + config.CacheConfig = &config.Cache{Memory: struct{}{}} + config.QueueConfig = &config.Queue{Memory: &config.QueueMemory{PoolSize: 10}} + + before := QueueGeneration() + Setup() + first := QueueGeneration() + Setup() + second := QueueGeneration() + + t.Logf("before=%d first=%d second=%d", before, first, second) + if first == before { + t.Fatal("the first Setup did not install a queue") + } + if second == first { + t.Fatal("a second Setup - which is what a configuration reload does - did not install a new one") + } +} From 2ac01ea5843a0692485cda6c2cfc393095bb389f Mon Sep 17 00:00:00 2001 From: zhangwenjian Date: Sat, 5 Sep 2026 23:18:01 +0800 Subject: [PATCH 2/2] =?UTF-8?q?test=E2=9C=85:=20restore=20what=20Setup=20w?= =?UTF-8?q?rites=20outside=20this=20test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Setup installs the cache and queue adapters on sdk.Runtime, which is a package-level singleton, and records what it installed in this package's own variables. The test left all of it behind, so what a later test in this binary saw depended on whether this one had run - the leak cmd/api's freshRuntime and common/middleware's copy of it exist to prevent. sdk.Runtime is swapped for a fresh one and everything is put back in Cleanup. --- common/storage/setup_gen_test.go | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/common/storage/setup_gen_test.go b/common/storage/setup_gen_test.go index d1c455ac..dc19ee65 100644 --- a/common/storage/setup_gen_test.go +++ b/common/storage/setup_gen_test.go @@ -3,7 +3,9 @@ package storage import ( "testing" + "github.com/go-admin-team/go-admin-core/v2/sdk" "github.com/go-admin-team/go-admin-core/v2/sdk/config" + "github.com/go-admin-team/go-admin-core/v2/sdk/runtime" ) // Issue #892: a configuration reload replaces the queue adapter and the @@ -16,8 +18,21 @@ import ( // queue for it to notice. Setup is what config re-runs on every change, so // calling it twice is what a reload does to this package. func TestSetupBumpsTheQueueGenerationOnEveryReload(t *testing.T) { + // Setup writes the process-wide sdk.Runtime - the cache and queue adapters - + // and this package's own record of what it installed. Restoring all of it + // keeps the test from deciding what a later test in this binary sees, + // which is the same isolation cmd/api's freshRuntime provides. prevQ, prevC := config.QueueConfig, config.CacheConfig - t.Cleanup(func() { config.QueueConfig, config.CacheConfig = prevQ, prevC }) + prevRuntime := sdk.Runtime + prevInstalled, prevGen := installed, installedGen + t.Cleanup(func() { + config.QueueConfig, config.CacheConfig = prevQ, prevC + sdk.Runtime = prevRuntime + queueMu.Lock() + installed, installedGen = prevInstalled, prevGen + queueMu.Unlock() + }) + sdk.Runtime = runtime.NewConfig() config.CacheConfig = &config.Cache{Memory: struct{}{}} config.QueueConfig = &config.Queue{Memory: &config.QueueMemory{PoolSize: 10}}