2022-05-02 09:35:49 +02:00

121 lines
2.2 KiB
Go

package photosapi
import (
"context"
"errors"
"math/rand"
"net/http"
"os"
"os/signal"
"time"
"github.com/gin-gonic/gin"
photosstore "gitlab.celogeek.com/photos/api/internal/photos/store"
"gorm.io/gorm"
)
var (
ErrReqNotFound = errors.New("this route doesn't exists")
ErrStorePathNotADirectory = errors.New("store path is not a directory")
)
type Service struct {
Gin *gin.Engine
DB *gorm.DB
Config *ServiceConfig
Store *photosstore.Store
Storage *Storage
LogOk *Logger
LogErr *Logger
}
type ServiceConfig struct {
Listen string
DB *DBConfig
StorePath string
}
func New(config *ServiceConfig) *Service {
return &Service{
Gin: gin.New(),
Config: config,
Store: &photosstore.Store{Path: config.StorePath},
Storage: &Storage{Path: config.StorePath},
LogOk: &Logger{os.Stdout, "Photos"},
LogErr: &Logger{os.Stderr, "Photos"},
}
}
func (s *Service) SetupRoutes() {
s.Gin.Use(
gin.Logger(),
s.Recovery,
s.RequireBody,
)
s.AccountInit()
s.MeInit()
s.FileInit()
s.UploadInit()
s.Gin.NoRoute(func(c *gin.Context) {
s.Error(c, http.StatusNotFound, ErrReqNotFound)
})
}
func (s *Service) PrepareStore() {
d, err := os.Stat(s.Store.Path)
if err != nil {
s.LogErr.Fatal("Store", err)
}
if !d.IsDir() {
s.LogErr.Fatal("Store", ErrStorePathNotADirectory)
}
}
func (s *Service) Run() error {
rand.Seed(time.Now().UnixNano())
s.PrepareStore()
s.SetupRoutes()
s.SetupDB()
go s.SessionCleaner()
srv := &http.Server{
Addr: s.Config.Listen,
Handler: s.Gin,
}
quit := make(chan os.Signal, 1)
var runError error
go func() {
// service connections
if runError = srv.ListenAndServe(); runError != nil {
quit <- os.Interrupt
}
}()
// Wait for interrupt signal to gracefully shutdown the server with
// a timeout of 5 seconds.
signal.Notify(quit, os.Interrupt)
<-quit
s.LogOk.Print("Exit", "shutdown ...")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
return err
}
db, err := s.DB.DB()
if err != nil {
return err
}
s.LogOk.Print("Exit", "closing database ...")
if err := db.Close(); err != nil {
return err
}
s.LogOk.Print("Exit", "exiting")
return runError
}