onasty/cmd/server/main.go(view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
package main
import (
"context"
"errors"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"github.com/gin-gonic/gin"
"github.com/olexsmir/onasty/internal/config"
"github.com/olexsmir/onasty/internal/hasher"
"github.com/olexsmir/onasty/internal/jwtutil"
"github.com/olexsmir/onasty/internal/logger"
"github.com/olexsmir/onasty/internal/mailer"
"github.com/olexsmir/onasty/internal/metrics"
"github.com/olexsmir/onasty/internal/service/notesrv"
"github.com/olexsmir/onasty/internal/service/usersrv"
"github.com/olexsmir/onasty/internal/store/psql/noterepo"
"github.com/olexsmir/onasty/internal/store/psql/sessionrepo"
"github.com/olexsmir/onasty/internal/store/psql/userepo"
"github.com/olexsmir/onasty/internal/store/psql/vertokrepo"
"github.com/olexsmir/onasty/internal/store/psqlutil"
httptransport "github.com/olexsmir/onasty/internal/transport/http"
"github.com/olexsmir/onasty/internal/transport/http/httpserver"
)
func main() {
if err := run(context.Background()); err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
}
//nolint:err113
func run(ctx context.Context) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
cfg := config.NewConfig()
// logger
logger, err := logger.NewCustomLogger(cfg.LogLevel, cfg.LogFormat, cfg.LogShowLine)
if err != nil {
return err
}
slog.SetDefault(logger)
// semi dev mode
if !cfg.IsDevMode() {
gin.SetMode(gin.ReleaseMode)
}
// app deps
psqlDB, err := psqlutil.Connect(ctx, cfg.PostgresDSN)
if err != nil {
return err
}
sha256Hasher := hasher.NewSHA256Hasher(cfg.PasswordSalt)
jwtTokenizer := jwtutil.NewJWTUtil(cfg.JwtSigningKey, cfg.JwtAccessTokenTTL)
mailGunMailer := mailer.NewMailgun(cfg.MailgunFrom, cfg.MailgunDomain, cfg.MailgunAPIKey)
sessionrepo := sessionrepo.New(psqlDB)
vertokrepo := vertokrepo.New(psqlDB)
userepo := userepo.New(psqlDB)
usersrv := usersrv.New(
userepo,
sessionrepo,
vertokrepo,
sha256Hasher,
jwtTokenizer,
mailGunMailer,
cfg.JwtRefreshTokenTTL,
cfg.VerificationTokenTTL,
cfg.AppURL,
)
noterepo := noterepo.New(psqlDB)
notesrv := notesrv.New(noterepo)
handler := httptransport.NewTransport(usersrv, notesrv)
// http server
srv := httpserver.NewServer(cfg.ServerPort, handler.Handler())
go func() {
slog.Info("starting http server", "port", cfg.ServerPort)
if err := srv.Start(); !errors.Is(err, http.ErrServerClosed) {
slog.Error("failed to start http server", "error", err)
}
}()
// metrics
if cfg.MetricsEnabled {
mSrv := httpserver.NewServer(cfg.MetricsPort, metrics.Handler())
go func() {
slog.Info("starting metrics server", "port", cfg.MetricsPort)
if err := mSrv.Start(); !errors.Is(err, http.ErrServerClosed) {
slog.Error("failed to start metrics server", "error", err)
}
}()
}
// graceful shutdown
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
<-quit
if err := srv.Stop(ctx); err != nil {
return errors.Join(errors.New("failed to stop http server"), err)
}
if err := psqlDB.Close(); err != nil {
return errors.Join(errors.New("failed to close postgres connection"), err)
}
return nil
}
|