73 lines
1.6 KiB
Go
73 lines
1.6 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"strconv"
|
|
"syscall"
|
|
"time"
|
|
)
|
|
|
|
func (app *application) serve() error {
|
|
maintenanceContext, stopMaintenance := context.WithCancel(context.Background())
|
|
defer stopMaintenance()
|
|
app.background(func() {
|
|
if err := app.runLifecycleMaintenance(time.Now()); err != nil {
|
|
app.logger.Error("lifecycle maintenance failed", "error", err)
|
|
}
|
|
ticker := time.NewTicker(6 * time.Hour)
|
|
defer ticker.Stop()
|
|
for {
|
|
select {
|
|
case <-maintenanceContext.Done():
|
|
return
|
|
case now := <-ticker.C:
|
|
if err := app.runLifecycleMaintenance(now); err != nil {
|
|
app.logger.Error("lifecycle maintenance failed", "error", err)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
srv := &http.Server{
|
|
Addr: net.JoinHostPort(app.config.Host, strconv.Itoa(app.config.Port)),
|
|
Handler: app.routes(),
|
|
IdleTimeout: time.Minute,
|
|
ReadHeaderTimeout: 5 * time.Second,
|
|
ReadTimeout: 2 * time.Minute,
|
|
WriteTimeout: 2 * time.Minute,
|
|
}
|
|
|
|
shutdownError := make(chan error)
|
|
|
|
go func() {
|
|
quit := make(chan os.Signal, 1)
|
|
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
|
s := <-quit
|
|
|
|
app.logger.Info("stopping server", "addr", srv.Addr, "signal", s.String())
|
|
shutdownError <- srv.Shutdown(context.Background())
|
|
}()
|
|
|
|
app.logger.Info("starting server", "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
|
|
}
|
|
|
|
stopMaintenance()
|
|
app.logger.Info("waiting for background tasks")
|
|
app.wg.Wait()
|
|
|
|
app.logger.Info("shutdown complete")
|
|
return nil
|
|
}
|