Documentation
¶
Overview ¶
Package safedown is for ensuring that applications shutdown gracefully and correctly. This includes the cases when an interrupt or termination signal is received, or when actions across go routines need to be coordinated.
Example ¶
Example demonstrates how setting up the safedown's shutdown actions works when a signal is received.
package main import ( "context" "fmt" "os" "time" "github.com/PeterEFinch/safedown" ) func main() { // This will send an interrupt signal after a second to simulate a signal // being sent from the outside. go func(pid int) { time.Sleep(time.Second) process := os.Process{Pid: pid} if err := process.Signal(os.Interrupt); err != nil { panic("unable to continue test: could not send signal to process") } }(os.Getpid()) sa := safedown.NewShutdownActions( safedown.ShutdownOnSignals(os.Interrupt), safedown.UseOnSignalFunc(func(signal os.Signal) { fmt.Printf("Signal received: %s\n", signal.String()) }), ) defer sa.Shutdown() ctx, cancel := context.WithCancel(context.Background()) sa.AddActions(cancel) fmt.Println("Processing starting") t := time.After(2 * time.Second) select { case <-ctx.Done(): fmt.Println("Context cancelled") case <-t: fmt.Println("Ticker ticked") } fmt.Println("Finished") }
Output: Processing starting Signal received: interrupt Context cancelled Finished
Example (NoSignal) ¶
Example_signalNotReceived demonstrates how setting up the safedown's shutdown actions works when no signal is received (and the program can terminate of its own accord).
package main import ( "context" "fmt" "os" "time" "github.com/PeterEFinch/safedown" ) func main() { sa := safedown.NewShutdownActions( safedown.ShutdownOnSignals(os.Interrupt), safedown.UseOnSignalFunc(func(signal os.Signal) { fmt.Printf("Signal received: %s\n", signal.String()) }), ) defer sa.Shutdown() ctx, cancel := context.WithCancel(context.Background()) sa.AddActions(cancel) fmt.Println("Processing starting") t := time.After(2 * time.Second) select { case <-ctx.Done(): fmt.Println("Context cancelled") case <-t: fmt.Println("Ticker ticked") } fmt.Println("Finished") }
Output: Processing starting Ticker ticked Finished
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option func(*config)
Option represents an option of the shutdown actions.
func ShutdownOnAnySignal ¶
func ShutdownOnAnySignal() Option
ShutdownOnAnySignal will enable shutdown to be triggered by any signal.
Using this option will likely lead to overzealous shutting down. It is recommended to use the option ShutdownOnSignals with the signals of interest.
This option will override ShutdownOnSignals if included after it.
func ShutdownOnSignals ¶
ShutdownOnSignals will enable the shutdown to be triggered by any of the signals included.
The choice of signals depends on the operating system and use-case.
This option will override ShutdownOnAnySignal if included after it.
func UseOnSignalFunc ¶
UseOnSignalFunc sets a function that will be called that if any signal that is listened for is received.
func UseOrder ¶
UseOrder determines the order the actions will be performed relative to the order they are added.
Example (FirstInFirstDone) ¶
ExampleUseOrder_firstInFirstDone demonstrates the "first in, first done" order.
package main import ( "fmt" "github.com/PeterEFinch/safedown" ) func main() { sa := safedown.NewShutdownActions( safedown.UseOrder(safedown.FirstInFirstDone), ) sa.AddActions(func() { fmt.Println("The first action added will be done first ...") }) sa.AddActions(func() { fmt.Println("... and the last action added will be done last.") }) sa.Shutdown() }
Output: The first action added will be done first ... ... and the last action added will be done last.
Example (FirstInLastDone) ¶
ExampleUseOrder_firstInFirstDone demonstrates the "first in, last done" order.
package main import ( "fmt" "github.com/PeterEFinch/safedown" ) func main() { sa := safedown.NewShutdownActions( safedown.UseOrder(safedown.FirstInLastDone), ) sa.AddActions(func() { fmt.Println("... and the first action added will be done last.") }) sa.AddActions(func() { fmt.Println("The last action added will be done first ...") }) sa.Shutdown() }
Output: The last action added will be done first ... ... and the first action added will be done last.
func UsePostShutdownStrategy ¶
func UsePostShutdownStrategy(strategy PostShutdownStrategy) Option
UsePostShutdownStrategy determines how the actions will be handled after Shutdown has been called or triggered via a signal.
The strategy is usually only used when the Shutdown has been triggered during the initialisation of an application.
Example ¶
ExampleUsePostShutdownStrategy demonstrates how to set a post shutdown strategy and its consequences.
package main import ( "fmt" "sync" "github.com/PeterEFinch/safedown" ) func main() { sa := safedown.NewShutdownActions( safedown.UsePostShutdownStrategy(safedown.PerformCoordinatelyInBackground), ) sa.AddActions(func() { fmt.Println("... and the first action added will be done after that.") }) sa.AddActions(func() { fmt.Println("The last action added will be done first ...") }) sa.Shutdown() wg := sync.WaitGroup{} wg.Add(1) sa.AddActions(func() { fmt.Println("The action added after shutdown is also done (provided we wait a little).") wg.Done() }) wg.Wait() }
Output: The last action added will be done first ... ... and the first action added will be done after that. The action added after shutdown is also done (provided we wait a little).
type Order ¶
type Order uint8
Order represents the order the actions will be performed relative to the order that they were added.
type PostShutdownStrategy ¶
type PostShutdownStrategy uint8
PostShutdownStrategy represents the strategy that should be applied to action added after shutdown has been triggered.
const ( DoNothing PostShutdownStrategy = iota // DoNothing means that any action added after shutdown has been trigger will not be done. PerformImmediately // PerformImmediately means that any action added after shutdown will be performed immediately (and block the AddAction method). PerformImmediatelyInBackground // PerformImmediatelyInBackground means that any action added after shutdown will be performed immediately in a go routine. PerformCoordinatelyInBackground // PerformCoordinatelyInBackground means that the shutdown actions will ATTEMPT to coordinate the actions added with all other actions which have already been added. )
type ShutdownActions ¶
type ShutdownActions struct {
// contains filtered or unexported fields
}
ShutdownActions represent a set of actions that are performed, i.e. functions that are called, when a service or computation is shutting down, ending or interrupted.
ShutdownActions must always be initialised using the NewShutdownActions function.
func NewShutdownActions ¶
func NewShutdownActions(options ...Option) *ShutdownActions
NewShutdownActions initialises shutdown actions.
In the event that options conflict, the later option will override the earlier option.
func (*ShutdownActions) AddActions ¶
func (sa *ShutdownActions) AddActions(actions ...func())
AddActions adds actions that are to be performed when Shutdown is called.
If Shutdown has already been called or trigger via a signal then the handling of the actions will depend on the post-shutdown strategy.
func (*ShutdownActions) Shutdown ¶
func (sa *ShutdownActions) Shutdown()
Shutdown will perform all actions that have been added.
This is an idempotent method and successive calls will have no affect.
Example ¶
ExampleShutdownActions_Shutdown demonstrates the default shutdown behaviour.
package main import ( "fmt" "github.com/PeterEFinch/safedown" ) func main() { sa := safedown.NewShutdownActions() sa.AddActions(func() { fmt.Println("The action is performed after shutdown is called.") }) fmt.Println("Code runs before shutdown is called.") sa.Shutdown() }
Output: Code runs before shutdown is called. The action is performed after shutdown is called.
func (*ShutdownActions) Wait ¶
func (sa *ShutdownActions) Wait()
Wait waits until the shutdown actions to have been performed.
If actions were added after Shutdown has been called or trigger via a signal then whether this method wait for those actions to be performed on the post-shutdown strategy and when the actions were added.