99 lines
2.1 KiB
Go
99 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/labstack/echo/v4"
|
|
"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
|
|
|
|
echoServer := echo.New()
|
|
|
|
echoServer.GET("/ping", func(c echo.Context) error {
|
|
return c.JSON(http.StatusOK, "pong")
|
|
})
|
|
|
|
addr := fmt.Sprintf("%s:%d", config.Addr, config.Port)
|
|
s.httpServer = &http.Server{
|
|
Addr: addr,
|
|
Handler: echoServer,
|
|
}
|
|
|
|
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")
|
|
}
|