Skip to content

Commit

Permalink
Add more documentation for method and types (#79)
Browse files Browse the repository at this point in the history
* Updated package Godoc

* Updated go code to specify that `WithName()` method is optional

* Added formatting in README.md

* Updated godoc for `WithName()` method

* Updated godoc for `NewWithSignals()` constructor

* Updated app example to use rootCtx

* Updated godoc for `Register()` constructor

* Updated godoc for `Hook` type
  • Loading branch information
skovtunenko committed Aug 2, 2022
1 parent 9f2cb22 commit 9ba2fb9
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 17 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ if err := terminator.Wait(appCtx, 20*time.Second); err != nil {

# 👀 Versioning

The library follows SemVer policy. With the release of v1.0.0 the public API is stable.
The library follows SemVer policy. With the release of **v1.0.0** the _public API is stable_.

# 📚 Example

Expand Down
16 changes: 11 additions & 5 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,27 @@
It is possible to set individual timeouts for each registered termination hook and global termination timeout for the whole application.
Optionally a Hook may have a name (using Hook.WithName). It might be handy only if the Logger injected into Terminator instance to
log internal termination lifecycle events.
Examples
Example code for generic application components:
func main() {
// Define Orders:
// Define termination Orders:
const (
HTTPServerTerminationOrder graterm.Order = 1
DBTerminationOrder graterm.Order = 2
)
// create new Terminator instance:
terminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)
terminator.SetLogger(log.Default()) // Optional step
// Register HTTP Server termination hook:
terminator.WithOrder(HTTPServerTerminationOrder).
WithName("HTTP Server").
WithName("HTTP Server"). // setting a Name is optional and will be useful only if logger instance provided
Register(1*time.Second, func(ctx context.Context) {
log.Println("terminating HTTP Server...")
defer log.Println("...HTTP Server terminated")
Expand Down Expand Up @@ -57,11 +61,13 @@
// create new Terminator instance:
terminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)
terminator.SetLogger(log.Default()) // Optional step
// Create an HTTP Server and add one simple handler into it:
httpServer := &http.Server{
Addr: ":8080",
Handler: http.DefaultServeMux,
ReadHeaderTimeout: 60 * time.Second, // fix for potential Slowloris Attack
Addr: ":8080",
Handler: http.DefaultServeMux,
}
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello, world!")
Expand All @@ -76,7 +82,7 @@
// Register HTTP Server termination hook:
terminator.WithOrder(HTTPServerTerminationOrder).
WithName("HTTPServer").
WithName("HTTPServer"). // setting a Name is optional and will be useful only if logger instance provided
Register(10*time.Second, func(ctx context.Context) {
if err := httpServer.Shutdown(ctx); err != nil {
log.Printf("shutdown HTTP Server: %+v\n", err)
Expand Down
9 changes: 6 additions & 3 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ func ExampleTerminator_WithOrder_1() {

// create new Terminator instance:
terminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)
terminator.SetLogger(log.Default()) // Optional step

// Register HTTP Server termination hook:
terminator.WithOrder(HTTPServerTerminationOrder).
WithName("HTTP Server").
WithName("HTTP Server"). // setting a Name is optional and will be useful only if logger instance provided
Register(1*time.Second, func(ctx context.Context) {
log.Println("terminating HTTP Server...")
defer log.Println("...HTTP Server terminated")
Expand All @@ -76,7 +77,7 @@ func ExampleTerminator_WithOrder_1() {

// Register Database termination hook:
terminator.WithOrder(DBTerminationOrder).
WithName("DB").
WithName("DB"). // setting a Name is optional and will be useful only if logger instance provided
Register(1*time.Second, func(ctx context.Context) {
log.Println("terminating DB...")
defer log.Println("...DB terminated")
Expand All @@ -102,6 +103,7 @@ func ExampleTerminator_WithOrder_2() {

// create new Terminator instance:
terminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)
terminator.SetLogger(log.Default()) // Optional step

// Create an HTTP Server and add one simple handler into it:
httpServer := &http.Server{
Expand All @@ -121,7 +123,7 @@ func ExampleTerminator_WithOrder_2() {

// Register HTTP Server termination hook:
terminator.WithOrder(HTTPServerTerminationOrder).
WithName("HTTPServer").
WithName("HTTPServer"). // setting a Name is optional and will be useful only if logger instance provided
Register(10*time.Second, func(ctx context.Context) {
if err := httpServer.Shutdown(ctx); err != nil {
log.Printf("shutdown HTTP Server: %+v\n", err)
Expand Down Expand Up @@ -164,6 +166,7 @@ func ExampleHook_WithName() {

// create new Terminator instance:
terminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)
terminator.SetLogger(log.Default()) // Optional step

// Register some hooks:
terminator.WithOrder(HTTPServerTerminationOrder).
Expand Down
11 changes: 9 additions & 2 deletions hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ const (
// Lower order - higher priority.
type Order int

// Hook is a registered termination hook.
// Hook is a registered ordered termination unit of work.
// I.e., the code that needs to be executed to perform resource cleanup or any other maintenance while shutting down the application.
//
// Do not create a Hook instance manually, use Terminator.WithOrder() method instead to get a Hook instance.
// Do NOT create a Hook instance manually, use Terminator.WithOrder() method instead to get a Hook instance.
type Hook struct {
terminator *Terminator // terminator is a pointer to Terminator instance that holds registered Hooks.

Expand All @@ -31,6 +32,9 @@ type Hook struct {
}

// WithName sets (optional) human-readable name of the registered termination [Hook].
//
// The Hook name will be useful only if Logger instance has been injected (using Terminator.SetLogger method) into Terminator
// to log internal termination lifecycle events.
func (h *Hook) WithName(name string) *Hook {
h.name = name
return h
Expand All @@ -39,6 +43,9 @@ func (h *Hook) WithName(name string) *Hook {
// Register registers termination [Hook] that should finish execution in less than given timeout.
//
// Timeout duration must be greater than zero; if not, timeout of 1 min will be used.
//
// The context value passed into hookFunc will be used only for cancellation signaling.
// I.e. to signal that Terminator will no longer wait on Hook to finish termination.
func (h *Hook) Register(timeout time.Duration, hookFunc func(ctx context.Context)) {
if timeout <= 0 {
timeout = defaultTimeout
Expand Down
16 changes: 10 additions & 6 deletions internal/example/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,12 @@ func main() {

logger.Println("Application started...")

terminator, appCtx := graterm.NewWithSignals(context.Background(), syscall.SIGINT, syscall.SIGTERM)
terminator.SetLogger(logger)
// ...Some root context for the whole application... (or it can be just context.Background())
rootCtx, rootCancel := context.WithCancel(context.Background())
defer rootCancel()

terminator, appCtx := graterm.NewWithSignals(rootCtx, syscall.SIGINT, syscall.SIGTERM)
terminator.SetLogger(logger) // Optional step

// Wire application components:
slowDB := NewSlowDB(terminator, logger)
Expand Down Expand Up @@ -116,7 +120,7 @@ func (s *Server) Init() {
}()

s.terminator.WithOrder(HTTPServerTerminationOrder).
WithName("HTTPServer").
WithName("HTTPServer"). // setting a Name is optional and will be useful only if logger instance provided
Register(httpServerTerminationTimeout, func(ctx context.Context) {
s.logger.Println("terminating HTTP Server component...")
defer s.logger.Println("...HTTP Server component terminated")
Expand All @@ -141,7 +145,7 @@ func NewMessaging(terminator *graterm.Terminator, logger *log.Logger) *Messaging
func (m *Messaging) Init() {
defer m.logger.Println("Messaging initialized")
m.terminator.WithOrder(MessagingTerminationOrder).
WithName("Messaging").
WithName("Messaging"). // setting a Name is optional and will be useful only if logger instance provided
Register(messagingTerminationTimeout, func(ctx context.Context) {
m.logger.Println("terminating Messaging component...")
defer m.logger.Println("...Messaging component terminated")
Expand All @@ -160,7 +164,7 @@ func NewFastDB(terminator *graterm.Terminator, logger *log.Logger) *FastDB {
func (d *FastDB) Init() {
defer d.logger.Println("FastDB initialized")
d.terminator.WithOrder(FastDBTerminationOrder).
WithName("FastDB").
WithName("FastDB"). // setting a Name is optional and will be useful only if logger instance provided
Register(fastDBTerminationTimeout, func(ctx context.Context) {
d.logger.Println("terminating FastDB component...")
defer d.logger.Println("...FastDB component terminated")
Expand All @@ -181,7 +185,7 @@ func NewSlowDB(terminator *graterm.Terminator, logger *log.Logger) *SlowDB {
func (d *SlowDB) Init() {
defer d.logger.Println("SlowDB initialized")
d.terminator.WithOrder(SlowDBTerminationOrder).
WithName("SlowDB").
WithName("SlowDB"). // setting a Name is optional and will be useful only if logger instance provided
Register(slowDBTerminationTimeout, func(ctx context.Context) {
d.logger.Println("terminating SlowDB component...")
defer d.logger.Println("...SlowDB component terminated")
Expand Down
3 changes: 3 additions & 0 deletions terminator.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ type Terminator struct {

// NewWithSignals creates a new instance of component Terminator.
//
// If the given appCtx parameter is canceled, the termination process will start for already registered Hook instances
// after calling Terminator.Wait method.
//
// Example of useful signals might be: [syscall.SIGINT], [syscall.SIGTERM].
//
// Note: this method will start internal monitoring goroutine.
Expand Down

0 comments on commit 9ba2fb9

Please sign in to comment.