Tooling to manage the execution of a process based on a Runnable interface:
type Runnable interface {
Run(context.Context) error
}And a simpler RunnableFunc interface:
type RunnableFunc func(context.Context) errorExample of an implementation of the command "yes":
func main() {
runnable.RunFunc(run)
}
func run(ctx context.Context) error {
for {
if ctx.Err() != nil {
return ctx.Err()
}
fmt.Println("y")
}
}To trigger a clean shutdown, a process must react to the termination signals (SIGINT, SIGTERM).
The Run() method is intended to be the process entrypoint:
- it immediately executes the runnable
- it cancels the context.Context when a termination signal is received
- it calls log.Fatal with the error if the runnable returned one
Example:
func main() {
runnable.Run(
app.Build(),
)
}The RunFunc() method is also provided for convenience.
The Restart runnable ensure that a component is running, even if it stops or crashes.
Example:
func main() {
runnable.Run(
runnable.Restart(
task.New(),
),
)
}The HTTPServer runnable starts and gracefully shutdowns a *http.Server.
Example:
func main() {
server := &http.Server{
Addr: "127.0.0.1:8000",
Handler: http.RedirectHandler("https://go.dev", 307),
}
runnable.Run(
runnable.HTTPServer(server),
)
}The Manager runnable starts and stops all runnables while respecting the dependency between them.
Components with dependencies will be stopped before their dependencies.
Example with three components:
g := runnable.Manager(nil)
g.Add(jobQueue)
g.Add(httpServer, jobQueue) // jobs is a dependency
g.Add(monitor)
runnable.Run(g.Build())Logs of a demo app
$ go run ./cmd/example
[RUNNABLE] 2020/10/22 22:42:26 INFO manager: main.JobQueue started
[RUNNABLE] 2020/10/22 22:42:26 INFO manager: runnable.httpServer started
[RUNNABLE] 2020/10/22 22:42:26 INFO manager: main.Monitor started
...
^C[RUNNABLE] 2020/10/22 22:42:34 INFO signal: received signal interrupt
[RUNNABLE] 2020/10/22 22:42:34 INFO manager: starting shutdown (context cancelled)
[RUNNABLE] 2020/10/22 22:42:34 INFO manager: runnable.httpServer cancelled
[RUNNABLE] 2020/10/22 22:42:34 INFO manager: main.Monitor cancelled
[RUNNABLE] 2020/10/22 22:42:34 INFO manager: main.Monitor stopped
[RUNNABLE] 2020/10/22 22:42:34 INFO manager: runnable.httpServer stopped
[RUNNABLE] 2020/10/22 22:42:34 INFO manager: main.JobQueue cancelled
[RUNNABLE] 2020/10/22 22:42:34 INFO manager: main.JobQueue stopped
[RUNNABLE] 2020/10/22 22:42:34 INFO manager: shutdown completeThe MIT License (MIT)