/
service.go
143 lines (117 loc) · 4.72 KB
/
service.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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package pkg
import (
"fmt"
"net"
"net/http"
"time"
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"
"github.com/JohnnyS318/RoyalAfgInGo/pkg/mw"
"github.com/JohnnyS318/RoyalAfgInGo/pkg/protos"
"github.com/JohnnyS318/RoyalAfgInGo/pkg/utils"
"github.com/JohnnyS318/RoyalAfgInGo/services/user/pkg/handlers"
"github.com/gorilla/mux"
"github.com/slok/go-http-metrics/metrics/prometheus"
"github.com/urfave/negroni"
"go.uber.org/zap"
"github.com/JohnnyS318/RoyalAfgInGo/pkg/config"
"github.com/JohnnyS318/RoyalAfgInGo/services/user/pkg/database"
"github.com/JohnnyS318/RoyalAfgInGo/services/user/pkg/metrics"
"github.com/JohnnyS318/RoyalAfgInGo/services/user/pkg/servers"
"github.com/JohnnyS318/RoyalAfgInGo/services/user/pkg/serviceconfig"
"github.com/Kamva/mgm"
"github.com/go-redis/cache/v8"
"github.com/go-redis/redis/v8"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/viper"
"go.mongodb.org/mongo-driver/mongo/options"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
metricsMW "github.com/slok/go-http-metrics/middleware"
metricsNegroni "github.com/slok/go-http-metrics/middleware/negroni"
)
// Start starts the user service
func Start(logger *zap.SugaredLogger) {
//###################### Redis ######################
//Connect to Redis and setup cache
red := redis.NewClient(&redis.Options{
Addr: viper.GetString(config.RedisAddress),
Username: viper.GetString(config.RedisUsername),
Password: viper.GetString(config.RedisPassword),
})
defer red.Close()
userCache := cache.New(&cache.Options{
Redis: red,
LocalCache: cache.NewTinyLFU(1000, time.Minute),
})
logger.Debugf("Redis configured to %v", viper.GetString(config.RedisAddress))
//###################### MONGO DB ######################
// Mongodb configuration
cfg := &mgm.Config{CtxTimeout: viper.GetDuration(serviceconfig.DatabaseTimeout)}
err := mgm.SetDefaultConfig(cfg, viper.GetString(serviceconfig.DatabaseName), options.Client().ApplyURI(viper.GetString(serviceconfig.DatabaseUrl)))
if err != nil {
logger.Fatalw("Could not set the mongodb config", "error", err)
}
//Connect to mongo
_, client, _, err := mgm.DefaultConfigs()
if err != nil {
logger.Fatalw("Connection to mongo failed", "error", err)
}
defer utils.DisconnectClient(logger, client)
logger.Debugf("Database connection established to [%v] with database name [%v]", viper.GetString(serviceconfig.DatabaseUrl), viper.GetString(serviceconfig.DatabaseName))
userDatabase := database.NewUserDatabase(logger, userCache)
//###################### STATUS REDIS DB ###########
//TODO: maybe a ring would be better
statusRed := redis.NewClient(&redis.Options{
Addr: viper.GetString(config.StatusRedisAddress),
Username: viper.GetString(config.StatusRedisUsername),
Password: viper.GetString(config.StatusRedisPassword),
})
defer statusRed.Close()
statusDB := database.NewOnlineStatusDatabase(logger, statusRed)
//###################### GRPC ######################
//Configure GRPC server
userServer := servers.NewUserServer(logger, userDatabase, statusDB, metrics.New())
gs := grpc.NewServer(
grpc.UnaryInterceptor(
grpc_middleware.ChainUnaryServer(
grpc_zap.UnaryServerInterceptor(logger.Desugar()),
grpc_recovery.UnaryServerInterceptor(),
),
),
)
protos.RegisterUserServiceServer(gs, userServer)
reflection.Register(gs)
l, err := net.Listen("tcp4", fmt.Sprintf(":%d", viper.Get(serviceconfig.Port)))
if err != nil {
logger.Fatalw("Unable to create listener", "error", err)
}
//Start the GRPC server
go utils.StartGrpcGracefully(logger, gs, l)
//###################### HTTP ######################
//HTTP Handlers
userHandler := handlers.NewUserHandler(logger, userDatabase, statusDB)
//Setup Routes
r := mux.NewRouter()
r.Handle("/api/user", mw.RequireAuth(userHandler.GetUser)).Methods(http.MethodGet)
r.Handle("/api/user", mw.RequireAuth(userHandler.UpdateUser)).Methods(http.MethodPut)
r.Handle("/metrics", promhttp.Handler())
//RegisterMiddleware
metricsMiddleware := metricsMW.New(metricsMW.Config{
Recorder: prometheus.NewRecorder(prometheus.Config{}),
Service: "authHTTP",
})
n := negroni.New(mw.NewLogger(logger.Desugar()), negroni.NewRecovery(), metricsNegroni.Handler("", metricsMiddleware))
n.UseHandler(r)
//Configure HTTP server
srv := &http.Server{
Addr: ":" + viper.GetString(config.HTTPPort),
WriteTimeout: time.Second * 15,
ReadTimeout: time.Second * 15,
IdleTimeout: time.Second * 60,
Handler: n,
}
//Start HTTP server
utils.StartGracefully(logger, srv, viper.GetDuration(config.GracefulShutdownTimeout))
}