File: example_test.go

package info (click to toggle)
golang-github-joshuarubin-lifecycle 1.1.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 108 kB
  • sloc: makefile: 2
file content (77 lines) | stat: -rw-r--r-- 1,871 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package lifecycle_test

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"time"

	"github.com/joshuarubin/lifecycle"
)

func Example() {
	// This is only to ensure that the example completes
	const timeout = 10 * time.Millisecond
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()

	// At the top of your application
	ctx = lifecycle.New(
		ctx,
		lifecycle.WithTimeout(30*time.Second), // optional
	)

	helloHandler := func(w http.ResponseWriter, req *http.Request) {
		_, _ = io.WriteString(w, "Hello, world!\n")
	}

	mux := http.NewServeMux()
	mux.HandleFunc("/hello", helloHandler)

	srv := &http.Server{
		Addr:    ":8080",
		Handler: mux,
	}

	var start, finish time.Time

	lifecycle.GoErr(ctx, func() error {
		start = time.Now()
		return srv.ListenAndServe()
	})

	lifecycle.DeferErr(ctx, func() error {
		finish = time.Now()
		fmt.Println("shutting down http server")
		// use a background context because we already have a timeout and when
		// Defer funcs run, ctx is necessarily canceled.
		return srv.Shutdown(context.Background())
	})

	// Any panics in Go or Defer funcs will be passed to the goroutine that Wait
	// runs in, so it is possible to handle them like this
	defer func() {
		if r := recover(); r != nil {
			panic(r) // example, you probably want to do something else
		}
	}()

	// Then at the end of main(), or run() or however your application operates
	//
	// The returned err is the first non-nil error returned by any func
	// registered with Go or Defer, otherwise nil.
	if err := lifecycle.Wait(ctx); err != nil && err != context.DeadlineExceeded {
		log.Fatal(err)
	}

	// This is just to show that the server will run for at least `timeout`
	// before shutting down
	if finish.Sub(start) < timeout {
		log.Fatal("didn't wait long enough to shutdown")
	}

	// Output:
	// shutting down http server
}