syz/server/server.go

100 lines
2.1 KiB
Go

package server
import (
"context"
"fmt"
"log/slog"
"net"
"net/http"
"time"
"git.zhouxhere.com/zhouxhere/syz/config"
"git.zhouxhere.com/zhouxhere/syz/store"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
"github.com/soheilhy/cmux"
"google.golang.org/grpc"
)
type Server struct {
config *config.Config
Store *store.Store
httpServer *http.Server
grpcServer *grpc.Server
}
func NewServer(ctx context.Context, config *config.Config, store *store.Store) *Server {
s := &Server{
Store: store,
}
s.config = config
if config.Mode == "prod" {
gin.SetMode(gin.ReleaseMode)
} else {
gin.SetMode(gin.DebugMode)
}
ginServer := gin.Default()
addr := fmt.Sprintf("%s:%d", config.Addr, config.Port)
s.httpServer = &http.Server{
Addr: addr,
Handler: ginServer,
}
grpcServer := grpc.NewServer()
s.grpcServer = grpcServer
return s
}
func (s *Server) Start(ctx context.Context) error {
addr := fmt.Sprintf("%s:%d", s.config.Addr, s.config.Port)
listener, err := net.Listen("tcp", addr)
if err != nil {
return errors.Wrap(err, "failed to listen")
}
muxServer := cmux.New(listener)
go func() {
grpcListener := muxServer.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
if err := s.grpcServer.Serve(grpcListener); err != nil {
slog.Error("failed to start grpc server", "error", err)
}
}()
go func() {
httpListener := muxServer.Match(cmux.HTTP1Fast(http.MethodPatch))
if err := s.httpServer.Serve(httpListener); err != nil {
slog.Error("failed to start http server", "error", err)
}
}()
go func() {
if err := muxServer.Serve(); err != nil {
slog.Error("failed to start server", "error", err)
}
}()
return nil
}
func (s *Server) Stop(ctx context.Context) {
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
if err := s.httpServer.Shutdown(ctx); err != nil {
slog.Error("failed to stop http server", "error", err)
}
s.grpcServer.GracefulStop()
if err := s.Store.Close(); err != nil {
slog.Error("failed to close store", "error", err)
}
slog.Info("server stopped")
}