-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add startup.Listeners struct to manage the start and stop of a generic Listener that complies with the Listener interface. Add startup.Service that handles a generic service. Add generic httpserver that complies with Listener interface. Add NewTracer to tracing package. AB#8170
- Loading branch information
Paul Hewlett
committed
Sep 22, 2023
1 parent
76db13c
commit e8f5803
Showing
9 changed files
with
208 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package httpserver | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"net/http" | ||
"time" | ||
) | ||
|
||
// A http server that has an inbuilt logger, name and complies wuth the Listener interface in | ||
// startup.Listeners. | ||
|
||
type HTTPServer struct { | ||
http.Server | ||
log Logger | ||
name string | ||
} | ||
|
||
func NewHTTPServer(log Logger, name string, port string, handler http.Handler) *HTTPServer { | ||
m := HTTPServer{ | ||
Server: http.Server{ | ||
Addr: ":" + port, | ||
Handler: handler, | ||
}, | ||
name: name, | ||
} | ||
m.log = log.WithIndex("httpserver", m.String()) | ||
// It is preferable to return a copy rather than a reference. Unfortunately http.Server has an | ||
// internal mutex and this cannot or should not be copied so we will return a reference instead. | ||
return &m | ||
} | ||
|
||
func (m *HTTPServer) String() string { | ||
// No logging here please | ||
return fmt.Sprintf("%s%s", m.name, m.Addr) | ||
} | ||
|
||
func (m *HTTPServer) Listen() error { | ||
m.log.Infof("httpserver starting") | ||
err := m.ListenAndServe() | ||
if err != nil { | ||
return fmt.Errorf("%s server terminated: %v", m, err) | ||
} | ||
return nil | ||
} | ||
|
||
func (m *HTTPServer) Shutdown(ctx context.Context) error { | ||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second) | ||
defer cancel() | ||
m.log.Infof("httpserver shutdown") | ||
return m.Server.Shutdown(ctx) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package httpserver | ||
|
||
import ( | ||
"github.com/rkvst/go-rkvstcommon/logger" | ||
) | ||
|
||
type Logger = logger.Logger |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package startup | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"os/signal" | ||
"syscall" | ||
"time" | ||
|
||
"golang.org/x/sync/errgroup" | ||
) | ||
|
||
// based on gist found at https://gist.github.com/pteich/c0bb58b0b7c8af7cc6a689dd0d3d26ef?permalink_comment_id=4053701 | ||
|
||
// Listener is an interface that describes any kind of listener - HTTP Server, GRPC Server | ||
// or servicebus receiver. | ||
type Listener interface { | ||
Listen() error | ||
Shutdown(context.Context) error | ||
} | ||
|
||
// Listeners contains all servers that comply with the service. | ||
type Listeners struct { | ||
name string | ||
log Logger | ||
listeners []Listener | ||
} | ||
|
||
type ListenersOption func(*Listeners) | ||
|
||
func WithListener(h Listener) ListenersOption { | ||
return func(l *Listeners) { | ||
l.listeners = append(l.listeners, h) | ||
} | ||
} | ||
|
||
func NewListeners(log Logger, name string, opts ...ListenersOption) Listeners { | ||
l := Listeners{log: log, name: name} | ||
for _, opt := range opts { | ||
opt(&l) | ||
} | ||
return l | ||
} | ||
|
||
func (l *Listeners) String() string { | ||
return l.name | ||
} | ||
|
||
func (l *Listeners) Listen() error { | ||
|
||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) | ||
defer stop() | ||
|
||
g, errCtx := errgroup.WithContext(ctx) | ||
|
||
for _, h := range l.listeners { | ||
h := h | ||
g.Go(func() error { | ||
err := h.Listen() | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
}) | ||
} | ||
|
||
g.Go(func() error { | ||
<-errCtx.Done() | ||
l.log.Infof("Cancel from signal") | ||
return l.Shutdown() | ||
}) | ||
|
||
err := g.Wait() | ||
if err != nil && !errors.Is(err, context.Canceled) { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (l *Listeners) Shutdown() error { | ||
var err error | ||
for _, h := range l.listeners { | ||
func() { | ||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) | ||
defer cancel() | ||
e := h.Shutdown(ctx) | ||
if e != nil { | ||
if err != nil { | ||
err = fmt.Errorf("Cannot shutdown %s: %w: %w", h, err, e) | ||
} else { | ||
err = fmt.Errorf("Cannot shutdown %s: %w", h, e) | ||
} | ||
} | ||
}() | ||
} | ||
return err | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package startup | ||
|
||
type ServiceProvider interface { | ||
Open() error | ||
Close() | ||
} | ||
|
||
// Service consists of a named ServiceProviders and a bunch of listeners. | ||
type Service struct { | ||
name string | ||
log Logger | ||
service ServiceProvider | ||
listeners Listeners | ||
} | ||
|
||
func NewService(log Logger, name string, service ServiceProvider, listeners Listeners) Service { | ||
s := Service{ | ||
name: name, | ||
service: service, | ||
listeners: listeners, | ||
} | ||
s.log = log.WithIndex("service", s.String()) | ||
return s | ||
} | ||
|
||
func (s *Service) String() string { | ||
return s.name | ||
} | ||
|
||
func (s *Service) Open() error { | ||
return s.service.Open() | ||
} | ||
|
||
func (s *Service) Close() { | ||
s.service.Close() | ||
} | ||
|
||
func (s *Service) Listen() error { | ||
return s.listeners.Listen() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters