From af9741ad5d197ee1e1273399e448d94355e67c6f Mon Sep 17 00:00:00 2001
From: Ming Deng <mindeng@ebay.com>
Date: Fri, 15 Nov 2019 00:02:48 +0800
Subject: [PATCH] Finish Test

---
 common/constant/key.go             |  1 +
 config/base_config_test.go         |  8 ++++++
 config/graceful_shutdown.go        | 41 +++++++++++++++---------------
 config/graceful_shutdown_config.go |  5 ++++
 registry/zookeeper/listener.go     |  8 +++++-
 registry/zookeeper/registry.go     | 11 +++-----
 6 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/common/constant/key.go b/common/constant/key.go
index 122b8e505..a275c6135 100644
--- a/common/constant/key.go
+++ b/common/constant/key.go
@@ -114,6 +114,7 @@ const (
 	ProtocolConfigPrefix       = "dubbo.protocols."
 	ProviderConfigPrefix       = "dubbo.provider."
 	ConsumerConfigPrefix       = "dubbo.consumer."
+	ShutdownConfigPrefix       = "dubbo.shutdown."
 )
 
 const (
diff --git a/config/base_config_test.go b/config/base_config_test.go
index 6dc3749e5..3684437d3 100644
--- a/config/base_config_test.go
+++ b/config/base_config_test.go
@@ -39,6 +39,7 @@ func Test_refresh(t *testing.T) {
 	mockMap["dubbo.com.MockService.MockService.GetUser.retries"] = "10"
 	mockMap["dubbo.consumer.check"] = "false"
 	mockMap["dubbo.application.name"] = "dubbo"
+	mockMap["dubbo.shutdown.timeout"] = "12s"
 
 	config.GetEnvInstance().UpdateExternalConfigMap(mockMap)
 
@@ -113,6 +114,13 @@ func Test_refresh(t *testing.T) {
 				},
 			},
 		},
+		ShutdownConfig: &ShutdownConfig{
+			Timeout:              "12s",
+			StepTimeout:          "2s",
+			RejectRequestHandler: "mock",
+			RejectRequest:        false,
+			RequestsFinished:     false,
+		},
 	}
 
 	c.SetFatherConfig(father)
diff --git a/config/graceful_shutdown.go b/config/graceful_shutdown.go
index eeb559b78..bbc7e64a7 100644
--- a/config/graceful_shutdown.go
+++ b/config/graceful_shutdown.go
@@ -79,24 +79,6 @@ func GracefulShutdownInit() {
 	}()
 }
 
-func totalTimeout() time.Duration {
-	var providerShutdown time.Duration = 0
-	if providerConfig != nil && providerConfig.ShutdownConfig != nil {
-		providerShutdown = providerConfig.ShutdownConfig.GetTimeout()
-	}
-
-	var consumerShutdown time.Duration = 0
-	if consumerConfig != nil && consumerConfig.ShutdownConfig != nil {
-		consumerShutdown = consumerConfig.ShutdownConfig.GetTimeout()
-	}
-
-	var timeout = providerShutdown
-	if consumerShutdown > providerShutdown {
-		timeout = consumerShutdown
-	}
-	return timeout
-}
-
 func BeforeShutdown() {
 
 	destroyAllRegistries()
@@ -104,6 +86,7 @@ func BeforeShutdown() {
 	// The value of configuration depends on how long the clients will get notification.
 	waitAndAcceptNewRequests()
 
+	time.Sleep(1 * time.Minute)
 	// reject the new request, but keeping waiting for accepting requests
 	waitForReceivingRequests()
 
@@ -116,7 +99,7 @@ func BeforeShutdown() {
 	// If this application is not the consumer, it will do nothing
 	destroyConsumerProtocols()
 
-	logger.Infof("Graceful shutdown --- Execute the custom callbacks.")
+	logger.Info("Graceful shutdown --- Execute the custom callbacks.")
 	customCallbacks := extension.GetAllCustomShutdownCallbacks()
 	for callback := customCallbacks.Front(); callback != nil; callback = callback.Next() {
 		callback.Value.(func())()
@@ -124,7 +107,7 @@ func BeforeShutdown() {
 }
 
 func destroyAllRegistries() {
-	logger.Infof("Graceful shutdown --- Destroy all registries. ")
+	logger.Info("Graceful shutdown --- Destroy all registries. ")
 	registryProtocol := extension.GetProtocol(constant.REGISTRY_KEY)
 	registryProtocol.Destroy()
 }
@@ -216,3 +199,21 @@ func waitingProcessedTimeout(shutdownConfig *ShutdownConfig) {
 		time.Sleep(10 * time.Millisecond)
 	}
 }
+
+func totalTimeout() time.Duration {
+	var providerShutdown time.Duration = 0
+	if providerConfig != nil && providerConfig.ShutdownConfig != nil {
+		providerShutdown = providerConfig.ShutdownConfig.GetTimeout()
+	}
+
+	var consumerShutdown time.Duration = 0
+	if consumerConfig != nil && consumerConfig.ShutdownConfig != nil {
+		consumerShutdown = consumerConfig.ShutdownConfig.GetTimeout()
+	}
+
+	var timeout = providerShutdown
+	if consumerShutdown > providerShutdown {
+		timeout = consumerShutdown
+	}
+	return timeout
+}
diff --git a/config/graceful_shutdown_config.go b/config/graceful_shutdown_config.go
index d7d21c149..9077752ce 100644
--- a/config/graceful_shutdown_config.go
+++ b/config/graceful_shutdown_config.go
@@ -21,6 +21,7 @@ import (
 	"time"
 )
 import (
+	"github.com/apache/dubbo-go/common/constant"
 	"github.com/apache/dubbo-go/common/logger"
 )
 
@@ -55,6 +56,10 @@ type ShutdownConfig struct {
 	RequestsFinished bool
 }
 
+func (config *ShutdownConfig) Prefix() string {
+	return constant.ShutdownConfigPrefix
+}
+
 func (config *ShutdownConfig) GetTimeout() time.Duration {
 	result, err := time.ParseDuration(config.Timeout)
 	if err != nil {
diff --git a/registry/zookeeper/listener.go b/registry/zookeeper/listener.go
index 67479c443..5a4cc2c66 100644
--- a/registry/zookeeper/listener.go
+++ b/registry/zookeeper/listener.go
@@ -109,7 +109,13 @@ func (l *RegistryConfigurationListener) Next() (*registry.ServiceEvent, error) {
 	}
 }
 func (l *RegistryConfigurationListener) Close() {
-	l.registry.wg.Done()
+	if l.registry.IsAvailable() {
+		/**
+		 * if the registry is not available, it means that the registry has been destroy
+		 * so we don't need to call Done(), or it will cause the negative count panic for registry.wg
+		 */
+		l.registry.wg.Done()
+	}
 }
 
 func (l *RegistryConfigurationListener) valid() bool {
diff --git a/registry/zookeeper/registry.go b/registry/zookeeper/registry.go
index 682b9fe0c..29ae51d44 100644
--- a/registry/zookeeper/registry.go
+++ b/registry/zookeeper/registry.go
@@ -173,14 +173,9 @@ func (r *zkRegistry) GetUrl() common.URL {
 }
 
 func (r *zkRegistry) Destroy() {
-	/**
-	 * Don't r.listener.Close()
-	 * here we don't close the listener because
-	 * the listener will be close in Subscribe().
-	 * We can not close it here. If we do that,
-	 * a negative count error of r.wg will occur because
-	 * we close the listener twice.
-	 */
+	if r.configListener != nil {
+		r.configListener.Close()
+	}
 	close(r.done)
 	r.wg.Wait()
 	r.closeRegisters()
-- 
GitLab