-
Notifications
You must be signed in to change notification settings - Fork 41
/
server.go
100 lines (91 loc) · 3.12 KB
/
server.go
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
package server
import (
"context"
"fmt"
"log"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/newrelic/go-agent/v3/integrations/nrgrpc"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_zap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
"github.com/odpf/stencil/server/api"
"github.com/odpf/stencil/server/config"
"github.com/odpf/stencil/server/logger"
stencilv1 "github.com/odpf/stencil/server/odpf/stencil/v1"
"github.com/odpf/stencil/server/proto"
"github.com/odpf/stencil/server/snapshot"
"github.com/odpf/stencil/server/store"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"google.golang.org/grpc"
"google.golang.org/grpc/health/grpc_health_v1"
)
// Router returns server router
func Router(api *api.API, config *config.Config) *runtime.ServeMux {
gwmux := runtime.NewServeMux()
router := gin.New()
addMiddleware(router, config)
registerCustomValidations(router)
registerRoutes(router, gwmux, api)
return gwmux
}
// Start Entry point to start the server
func Start() {
ctx := context.Background()
config := config.LoadConfig()
db := store.NewDBStore(config)
stRepo := snapshot.NewSnapshotRepository(db)
protoRepo := proto.NewProtoRepository(db)
protoService := proto.NewService(protoRepo, stRepo)
api := &api.API{
Store: protoService,
Metadata: stRepo,
}
port := fmt.Sprintf(":%s", config.Port)
nr := getNewRelic(config)
mux := Router(api, config)
// init grpc server
opts := []grpc.ServerOption{
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
grpc_recovery.UnaryServerInterceptor(),
grpc_ctxtags.UnaryServerInterceptor(),
nrgrpc.UnaryServerInterceptor(nr),
grpc_zap.UnaryServerInterceptor(logger.Logger))),
grpc.MaxRecvMsgSize(config.GRPC.MaxRecvMsgSizeInMB << 20),
grpc.MaxSendMsgSize(config.GRPC.MaxSendMsgSizeInMB << 20),
}
// Create a gRPC server object
s := grpc.NewServer(opts...)
stencilv1.RegisterStencilServiceServer(s, api)
grpc_health_v1.RegisterHealthServer(s, api)
conn, err := grpc.DialContext(
context.Background(),
port,
grpc.WithInsecure(),
)
if err != nil {
log.Fatalln("Failed to dial server:", err)
}
stencilv1.RegisterStencilServiceHandler(ctx, mux, conn)
runWithGracefulShutdown(config, grpcHandlerFunc(s, mux), func() {
conn.Close()
s.GracefulStop()
db.Close()
})
}
// grpcHandlerFunc returns an http.Handler that delegates to grpcServer on incoming gRPC
// connections or otherHandler otherwise.
func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler {
return h2c.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// This is a partial recreation of gRPC's internal checks https://github.com/grpc/grpc-go/pull/514/files#diff-95e9a25b738459a2d3030e1e6fa2a718R61
if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
grpcServer.ServeHTTP(w, r)
} else {
otherHandler.ServeHTTP(w, r)
}
}), &http2.Server{})
}