Files
go-playground/projects/greenlight/cmd/api/server.go
T

79 lines
1.7 KiB
Go

package main
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
func (app *application) serve() error {
srv := &http.Server{
Addr: fmt.Sprintf(":%d", app.config.port),
Handler: app.routes(),
IdleTimeout: time.Minute,
ReadTimeout: 10 * time.Second,
WriteTimeout: 30 * time.Second,
}
shutdownError := make(chan error)
go func() {
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
s := <-quit
app.logger.PrintInfo("caught signal", map[string]string{
"signal": s.String(),
})
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
// Call Shutdown() on the server like before, but now we only send on the
// shutdownError channel if it returns an error.
err := srv.Shutdown(ctx)
if err != nil {
shutdownError <- err
}
// Log a message to say that we're waiting for any background goroutines to
// complete their tasks.
app.logger.PrintInfo("completing background tasks", map[string]string{
"addr": srv.Addr,
})
// Call Wait() to block until our WaitGroup counter is zero --- essentially
// blocking until the background goroutines have finished. Then we return nil on
// the shutdownError channel, to indicate that the shutdown completed without
// any issues.
app.wg.Wait()
shutdownError <- nil
}()
app.logger.PrintInfo("starting server", map[string]string{
"addr": srv.Addr,
"env": app.config.env,
})
err := srv.ListenAndServe()
if !errors.Is(err, http.ErrServerClosed) {
return err
}
err = <-shutdownError
if err != nil {
return err
}
app.logger.PrintInfo("stopped server", map[string]string{
"addr": srv.Addr,
})
return nil
}