From 84d4cb072601c04ef881761cff17e4e5c7be6ded Mon Sep 17 00:00:00 2001 From: Michael Nussbaum Date: Tue, 5 Oct 2021 11:24:18 -0700 Subject: [PATCH] Implement HTTP service stop with a 5 sec timeout (#209) * Implement HTTP service stop with a 5 sec timeout * No need to wrap the cancellation in an extra func * Address lint errors, camel case variables --- service/http/service.go | 23 ++++++++++++++--------- service/http/service_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/service/http/service.go b/service/http/service.go index 63007a2..b64b053 100644 --- a/service/http/service.go +++ b/service/http/service.go @@ -1,7 +1,9 @@ package http import ( + "context" "net/http" + "time" "github.com/dapr/go-sdk/service/common" ) @@ -21,7 +23,11 @@ func newServer(address string, mux *http.ServeMux) *Server { mux = http.NewServeMux() } return &Server{ - address: address, + address: address, + httpServer: &http.Server{ + Addr: address, + Handler: mux, + }, mux: mux, topicSubscriptions: make([]*common.Subscription, 0), } @@ -31,23 +37,22 @@ func newServer(address string, mux *http.ServeMux) *Server { type Server struct { address string mux *http.ServeMux + httpServer *http.Server topicSubscriptions []*common.Subscription } // Start starts the HTTP handler. Blocks while serving. func (s *Server) Start() error { s.registerSubscribeHandler() - server := http.Server{ - Addr: s.address, - Handler: s.mux, - } - return server.ListenAndServe() + return s.httpServer.ListenAndServe() } -// Stop stops previously started HTTP service. +// Stop stops previously started HTTP service with a five second timeout. func (s *Server) Stop() error { - // TODO: implement service stop - return nil + ctxShutDown, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + return s.httpServer.Shutdown(ctxShutDown) } func setOptions(w http.ResponseWriter, r *http.Request) { diff --git a/service/http/service_test.go b/service/http/service_test.go index 91ec0ea..f4ca4e9 100644 --- a/service/http/service_test.go +++ b/service/http/service_test.go @@ -4,6 +4,7 @@ import ( "net/http" "net/http/httptest" "testing" + "time" "github.com/stretchr/testify/assert" ) @@ -15,6 +16,31 @@ func TestStoppingUnstartedService(t *testing.T) { assert.NoError(t, err) } +func TestStoppingStartedService(t *testing.T) { + s := newServer(":3333", nil) + assert.NotNil(t, s) + + go func() { + if err := s.Start(); err != nil && err != http.ErrServerClosed { + panic(err) + } + }() + // Wait for the server to start + time.Sleep(200 * time.Millisecond) + assert.NoError(t, s.Stop()) +} + +func TestStartingStoppedService(t *testing.T) { + s := newServer(":3333", nil) + assert.NotNil(t, s) + stopErr := s.Stop() + assert.NoError(t, stopErr) + + startErr := s.Start() + assert.Error(t, startErr, "expected starting a stopped server to raise an error") + assert.Equal(t, startErr.Error(), http.ErrServerClosed.Error()) +} + func TestSettingOptions(t *testing.T) { req, err := http.NewRequest(http.MethodOptions, "/", nil) assert.NoErrorf(t, err, "error creating request")