Source File
task.go
Belonging Package
go.pact.im/x/process
package process
import (
)
// Leaf converts a “leaf” function to a runnable process function that accepts
// callback. It accepts an optional gracefulStop function to perform graceful
// shutdown. If the function is nil, the process will be terminated by context
// cancellation instead.
//
// The resulting Runnable returns first non-nil error from functions in the
// following order: callback, gracefulStop, runInForeground. That is, if both
// callback and gracefulStop return a non-nil error, the latter is ignored.
//
// Example (HTTP):
//
// var lis net.Listener
// var srv *http.Server
//
// process.Leaf(
// func(_ context.Context) error {
// err := srv.Serve(lis)
// if errors.Is(err, http.ErrServerClosed) {
// return nil
// }
// return err
// },
// func(ctx context.Context) error {
// err := srv.Shutdown(ctx)
// if err != nil {
// return srv.Close()
// }
// return nil
// },
// )
//
// Example (gRPC):
//
// var lis net.Listener
// var srv *grpc.Server
//
// process.Leaf(
// func(_ context.Context) error {
// return srv.Serve(lis)
// },
// func(ctx context.Context) error {
// done := make(chan struct{})
// go func() {
// srv.GracefulStop()
// close(done)
// }()
// select {
// case <-ctx.Done():
// srv.Stop()
// <-done
// case <-done:
// }
// return nil
// },
// )
//
// Alternatively, use [go.pact.im/x/grpcprocess] package for gRPC.
//
func (, func( context.Context) error) Runnable {
return &leafRunnable{, }
}
type leafRunnable struct {
runInForeground func(ctx context.Context) error
gracefulStop func(ctx context.Context) error
}
func ( *leafRunnable) ( context.Context, Callback) error {
, := context.WithCancel()
defer ()
var sync.WaitGroup
.Add(1)
var error
go func() {
defer .Done()
= .runInForeground()
() // cancel callback
}()
:= ()
var error
if .gracefulStop != nil {
= .gracefulStop()
}
()
.Wait()
switch {
case != nil:
return
case != nil:
return
}
return
}
// StartStop returns a Runnable instance for the pair of start/stop functions.
// The stop function should perform a graceful shutdown until a context expires,
// then proceed with a forced shutdown.
//
// The resulting Runnable returns either start error or the first non-nil error
// from callback and stop functions. If both callback and stop return a non-nil
// error, the latter is ignored.
func (, func( context.Context) error) Runnable {
return &startStopRunnable{, }
}
type startStopRunnable struct {
startInBackground func(ctx context.Context) error
gracefulStop func(ctx context.Context) error
}
func ( *startStopRunnable) ( context.Context, Callback) error {
if := .startInBackground(); != nil {
return
}
:= ()
if := .gracefulStop(); != nil && == nil {
return
}
return
}
The pages are generated with Golds v0.4.9. (GOOS=linux GOARCH=amd64)