AlexStocks commented on code in PR #3612:
URL: https://github.com/apache/dubbo-go/pull/3612#discussion_r3810174359
##########
config_center/zookeeper/impl_test.go:
##########
@@ -126,6 +138,335 @@ func TestGetPropertiesWithMockZk(t *testing.T) {
require.Empty(t, empty)
}
+func TestLoadPropertiesRegistersWatchOnlyWhenInactive(t *testing.T) {
+ cluster, client, events, err :=
gxzookeeper.NewMockZookeeperClient("watch-selection", 5*time.Second)
+ if err != nil {
+ t.Skipf("skip mock zk setup: %v", err)
+ }
+ defer cluster.Stop()
+
+ cfg := &zookeeperDynamicConfiguration{
+ rootPath: "/dubbo/config",
+ client: client,
+ url: mustURL(t, "registry://127.0.0.1:2181"),
+ cache: newConfigCache(time.Minute),
+ }
+ activePath := cfg.getPath("active", "group")
+ inactivePath := cfg.getPath("inactive", "group")
+ require.NoError(t, cfg.PublishConfig("active", "group", "v1"))
+ require.NoError(t, cfg.PublishConfig("inactive", "group", "v1"))
+
+ waitForEvent := func(path string, timeout time.Duration) bool {
+ timer := time.NewTimer(timeout)
+ defer timer.Stop()
+ for {
+ select {
+ case event := <-events:
+ if event.Path == path && event.Type ==
zk.EventNodeDataChanged {
+ return true
+ }
+ case <-timer.C:
+ return false
+ }
+ }
+ }
+
+ activeWatcher := &zk.Watcher{}
+ _, watcher, err := cfg.loadProperties(activePath, activeWatcher, false)
+ require.NoError(t, err)
+ require.Same(t, activeWatcher, watcher)
+ _, stat, err := client.GetContent(activePath)
+ require.NoError(t, err)
+ _, err = client.SetContent(activePath, []byte("v2"), stat.Version)
+ require.NoError(t, err)
+ require.False(t, waitForEvent(activePath, time.Second))
+
+ _, watcher, err = cfg.loadProperties(inactivePath, nil, true)
+ require.NoError(t, err)
+ require.NotNil(t, watcher)
+ _, stat, err = client.GetContent(inactivePath)
+ require.NoError(t, err)
+ _, err = client.SetContent(inactivePath, []byte("v2"), stat.Version)
+ require.NoError(t, err)
+ require.True(t, waitForEvent(inactivePath, time.Second))
+}
+
+func TestListenerUsesGroupOption(t *testing.T) {
+ cluster, client, _, err :=
gxzookeeper.NewMockZookeeperClient("listener-group", 5*time.Second)
+ if err != nil {
+ t.Skipf("skip mock zk setup: %v", err)
+ }
+ defer cluster.Stop()
+
+ zkListener := remotingzookeeper.NewZkEventListener(client)
+ defer zkListener.Close()
+ cfg := &zookeeperDynamicConfiguration{
+ rootPath: "/dubbo/config",
+ client: client,
+ url: mustURL(t, "registry://127.0.0.1:2181"),
+ cache: newConfigCache(time.Minute),
+ listener: zkListener,
+ }
+ cfg.cacheListener = newCacheListener(cfg.rootPath, zkListener,
&cfg.cache)
+ key := "app.properties"
+ group := "custom"
+ path := cfg.getPropertiesPath(key, config_center.WithGroup(group))
+ rec := &recListener{}
+
+ cfg.AddListener(key, rec, config_center.WithGroup(group))
+ _, ok := cfg.cacheListener.keyListeners.Load(path)
+ require.True(t, ok)
+
+ cfg.RemoveListener(key, rec, config_center.WithGroup(group))
+ _, ok = cfg.cacheListener.keyListeners.Load(path)
+ require.False(t, ok)
+}
+
+func TestGetPropertiesFallsBackToTTLAtAutoWatchLimit(t *testing.T) {
+ cluster, client, events, err :=
gxzookeeper.NewMockZookeeperClient("watch-limit", 5*time.Second)
+ if err != nil {
+ t.Skipf("skip mock zk setup: %v", err)
+ }
+ defer cluster.Stop()
+
+ cfg := &zookeeperDynamicConfiguration{
+ rootPath: "/dubbo/config",
+ client: client,
+ url: mustURL(t, "registry://127.0.0.1:2181"),
+ cache: newConfigCache(time.Minute),
+ }
+ for i := range maxAutoWatches {
+ require.True(t, cfg.cache.setWatch(fmt.Sprintf("/watch/%d", i),
configWatchState{
+ watcher: &zk.Watcher{},
+ auto: true,
+ }))
+ }
+
+ require.NoError(t, cfg.PublishConfig("fallback", "group", "v1"))
+ value, err := cfg.GetProperties("fallback",
config_center.WithGroup("group"))
+ require.NoError(t, err)
+ require.Equal(t, "v1", value)
+
+ path := cfg.getPath("fallback", "group")
+ _, watchState := cfg.cache.snapshot(path)
+ require.False(t, watchState.tracked())
+ require.Equal(t, maxAutoWatches, cfg.cache.autoWatchCount)
+ require.Zero(t, cfg.cache.autoWatchReservations)
+ _, stat, err := client.GetContent(path)
+ require.NoError(t, err)
+ _, err = client.SetContent(path, []byte("v2"), stat.Version)
+ require.NoError(t, err)
+
+ timer := time.NewTimer(100 * time.Millisecond)
+ defer timer.Stop()
+ for {
+ select {
+ case event := <-events:
+ if event.Path == path && event.Type ==
zk.EventNodeDataChanged {
+ t.Fatal("TTL fallback should not register an
auto watch")
+ }
+ case <-timer.C:
+ value, err = cfg.GetProperties("fallback",
config_center.WithGroup("group"))
+ require.NoError(t, err)
+ require.Equal(t, "v1", value)
+ return
+ }
+ }
+}
+
+func TestGetPropertiesCacheUpdatedByWatch(t *testing.T) {
+ cluster, client, _, err :=
gxzookeeper.NewMockZookeeperClient("cache-watch", 5*time.Second)
+ if err != nil {
+ t.Skipf("skip mock zk setup: %v", err)
+ }
+ defer cluster.Stop()
+ go (&gxzookeeper.DefaultHandler{}).HandleZkEvent(client)
+
+ cfg := &zookeeperDynamicConfiguration{
+ rootPath: "/dubbo/config",
+ client: client,
+ done: make(chan struct{}),
+ url: mustURL(t, "registry://127.0.0.1:2181"),
+ cache: newConfigCache(time.Minute),
+ }
+ cfg.listener = remotingzookeeper.NewZkEventListener(client)
+ cfg.cacheListener = newCacheListener(cfg.rootPath, cfg.listener,
&cfg.cache)
+ cfg.listener.ListenConfigurationEvent(cfg.rootPath, cfg.cacheListener)
+ defer cfg.listener.Close()
Review Comment:
[P1] 让新增的 ZooKeeper 回归测试真正运行并能结束
这些 watch/reconnect 用例目前没有形成有效门禁:当前 Unit Test 日志里该包只运行了约 0.113s/1.409s;在同样缺少
ZooKeeper fat jar 的环境下用 `-v` 执行时,本用例以及两个 reconnect 用例都被 `t.Skipf` 跳过。补入经
SHA-512 校验的 Apache ZooKeeper 3.4.14 fat jar
后,`TestGetPropertiesCacheUpdatedByWatch` 和
`TestRestartCallBackRestoresBusinessListener` 都完成了业务断言,但在这里调用 `Close()`
后稳定超时,goroutine 栈停在 `ZkEventListener.Close -> wg.Wait`。原因是
`ListenConfigurationEvent` 执行了 `wg.Add(1)`,启动的 goroutine 却没有对应 `Done()`;隔离探针只增加
`defer l.wg.Done()` 后,三个真实 ZK 用例及其 `-race` 运行均通过。请补齐 WaitGroup 配对,并让 CI 显式提供
ZooKeeper 测试依赖(或在缺失时失败),否则当前绿色检查既隐藏了主路径未执行,也会在依赖齐全的环境中永久阻塞。
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]