...

Source file src/edge-infra.dev/pkg/edge/datasync/internal/shutdown/graceful.go

Documentation: edge-infra.dev/pkg/edge/datasync/internal/shutdown

     1  package shutdown
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  	"os"
     7  	"os/signal"
     8  	"time"
     9  
    10  	syscall "golang.org/x/sys/unix"
    11  
    12  	"edge-infra.dev/pkg/lib/logging"
    13  )
    14  
    15  type Graceful struct {
    16  	term   chan os.Signal
    17  	fail   chan error
    18  	logger *logging.EdgeLogger
    19  }
    20  
    21  func NewGraceful() *Graceful {
    22  	return &Graceful{
    23  		term:   make(chan os.Signal),
    24  		fail:   make(chan error),
    25  		logger: logging.NewLogger(),
    26  	}
    27  }
    28  
    29  // Serve graceful
    30  func (g *Graceful) Serve(doWork func() error, teardown func(context.Context) error) error {
    31  	go func() {
    32  		signal.Notify(g.term, syscall.SIGINT, syscall.SIGTERM)
    33  		<-g.term // waits for termination signal
    34  
    35  		// context with 30s timeout
    36  		ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    37  		defer cancel()
    38  
    39  		// all teardown process must complete within 30 seconds
    40  		g.fail <- teardown(ctx)
    41  	}()
    42  
    43  	// doWork blocks our code from exit, but will produce ErrServerClosed when stopped
    44  	if err := doWork(); err != nil && err != http.ErrServerClosed {
    45  		g.logger.Error(err, "doWork had an error")
    46  		return err
    47  	}
    48  
    49  	// after server gracefully stopped, code proceeds here and waits for any error produced by teardown() process
    50  	return <-g.fail
    51  }
    52  

View as plain text