-
Notifications
You must be signed in to change notification settings - Fork 0
/
context.go
76 lines (72 loc) · 2.27 KB
/
context.go
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
// SPDX-License-Identifier: MIT
//
// Copyright 2021 Andrew Bursavich. All rights reserved.
// Use of this source code is governed by The MIT License
// which can be found in the LICENSE file.
package graceful
import (
"context"
"os"
"os/signal"
"syscall"
"time"
"github.com/go-logr/logr"
)
// Contexts returns three contexts which respectively serve as warning, soft,
// and hard shutdown signals. They are cancelled after TERM or INT signals are
// received.
//
// When a shutdown signal is received, the warning context is cancelled. This is
// useful to start failing health checks while other traffic is still served.
//
// If delay is positive, the soft context will be cancelled after that duration.
// This is useful to allow loadbalancer updates before the server stops accepting
// new requests.
//
// If grace is positive, the hard context will be cancelled that duration after
// the soft context is cancelled. This is useful to set a maximum time to allow
// pending requests to complete.
//
// Repeated TERM or INT signals will bypass any delay or grace time.
func Contexts(ctx context.Context, log logr.Logger, delay, grace time.Duration) (warn, soft, hard context.Context) {
sigCh := make(chan os.Signal, 3)
signal.Notify(sigCh, syscall.SIGTERM, syscall.SIGINT)
hardCtx, hardCancel := context.WithCancel(ctx)
softCtx, softCancel := context.WithCancel(hardCtx)
warnCtx, warnCancel := context.WithCancel(softCtx)
go func() {
defer signal.Stop(sigCh)
defer hardCancel()
select {
case sig := <-sigCh:
log.Info("Shutdown triggered", "signal", sig.String())
case <-ctx.Done():
return
}
if delay > 0 {
log.Info("Shutdown starting after delay period", "duration", delay)
warnCancel()
select {
case <-time.After(delay):
log.Info("Shutdown delay period ended")
case sig := <-sigCh:
log.Info("Skipping shutdown delay period", "signal", sig.String())
case <-ctx.Done():
return
}
}
if grace > 0 {
log.Info("Shutdown starting with grace period", "duration", grace)
softCancel()
select {
case <-time.After(grace):
log.Info("Shutdown grace period ended")
case sig := <-sigCh:
log.Info("Skipping shutdown grace period", "signal", sig.String())
case <-ctx.Done():
return
}
}
}()
return warnCtx, softCtx, hardCtx
}