Skip to content

Commit

Permalink
feat: add grpc server
Browse files Browse the repository at this point in the history
  • Loading branch information
Bastien Rigaud committed Feb 16, 2024
1 parent 9a9505a commit a1e5f9b
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 67 deletions.
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@ module github.com/Golerplate/user-store-svc
go 1.21.5

require (
github.com/Golerplate/contracts v0.0.1
github.com/Golerplate/pkg v0.0.2
github.com/bufbuild/connect-go v1.10.0
github.com/bufbuild/connect-grpcreflect-go v1.1.0
github.com/caarlos0/env/v8 v8.0.0
github.com/go-sql-driver/mysql v1.7.1
github.com/golang/protobuf v1.5.3
github.com/rs/zerolog v1.32.0
golang.org/x/net v0.21.0
google.golang.org/protobuf v1.32.0
)

require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pkg/errors v0.9.1 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
)
22 changes: 22 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,15 +1,32 @@
github.com/Golerplate/contracts v0.0.1 h1:OtKvpCKVQGTjLFbxYPBkHn/ZC5wQoaumfTlpNuvSmO4=
github.com/Golerplate/contracts v0.0.1/go.mod h1:ALtjMgMcSLE6wGcB2zGIWand81y0HsU+MIvn1mmBP+0=
github.com/Golerplate/pkg v0.0.2 h1:b1T2Rky4BaJ5c9bHeh0cVII8M1LWcvKfzDJkGmT/G5w=
github.com/Golerplate/pkg v0.0.2/go.mod h1:xj+tuGKV3MtOpy/B6SMBJ0EkbaXMaivufhce/SzwqRk=
github.com/Trade-Arcade-Inc/shared v0.7.140 h1:UMZgktYy/vvk2L5S4jdjmXuRLBGh1Gq7Szxakb8J228=
github.com/Trade-Arcade-Inc/shared v0.7.140/go.mod h1:izkLhXVU2B6XIoBfvx9cRmcySl1lUKrRhUjV17Oc1Hw=
github.com/bufbuild/connect-go v1.10.0 h1:QAJ3G9A1OYQW2Jbk3DeoJbkCxuKArrvZgDt47mjdTbg=
github.com/bufbuild/connect-go v1.10.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8=
github.com/bufbuild/connect-grpcreflect-go v1.1.0 h1:T0FKu1y9zZW4cjHuF+Q7jIN6ek8HTpCxOP8ZsORZICg=
github.com/bufbuild/connect-grpcreflect-go v1.1.0/go.mod h1:AxcY2fSAr+oQQuu+K35qy2VDtX+LWr7SrS2SvfjY898=
github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0=
github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
Expand All @@ -23,3 +40,8 @@ golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
67 changes: 41 additions & 26 deletions src/cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,45 +1,60 @@
package main

import (
"context"
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"

"github.com/Golerplate/user-store-svc/src/internal/config"
handler_user_v1 "github.com/Golerplate/user-store-svc/src/internal/handler/user/v1"
server_user_v1 "github.com/Golerplate/user-store-svc/src/internal/server/user/v1"
"github.com/Golerplate/user-store-svc/src/internal/service"
"github.com/rs/zerolog/log"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"

serviceDatastore "github.com/Golerplate/user-store-svc/src/internal/service/datastore/planetscale"
)

func main() {
// ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(context.Background())

// sigs := make(chan os.Signal, 1)
// signal.Notify(sigs, syscall.SIGTERM)
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM)

// cfg := config.GetServiceConfig()
cfg := config.GetServiceConfig()

// userStoreServiceDatastore := serviceDatastore.NewPlanetScaleDatastore()
// userStoreService := service.NewUserStoreService(userStoreServiceDatastore)
// userStoreServiceHandler := handler_user_v1.NewUserStoreServiceHandler(userStoreService)
userStoreServiceDatastore := serviceDatastore.NewPlanetScaleDatastore()
userStoreService := service.NewUserStoreService(userStoreServiceDatastore)
userStoreServiceHandler := handler_user_v1.NewUserStoreServiceHandler(userStoreService)

// grpcBuilder := server_user_v1.NewGRPCBuilder(userStoreServiceHandler)
grpcBuilder := server_user_v1.NewGRPCBuilder(userStoreServiceHandler)

// grpcServer := http.Server{
// Addr: fmt.Sprintf(":%d", cfg.GRPCServerConfig.Port),
// Handler: h2c.NewHandler(grpcBuilder, &http2.Server{}),
// }
grpcServer := http.Server{
Addr: fmt.Sprintf(":%d", cfg.GRPCServerConfig.Port),
Handler: h2c.NewHandler(grpcBuilder, &http2.Server{}),
}

// go func() {
// if err := grpcServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
// log.Fatal().Err(err).Msg("unable to start grpc server")
// }
// }()
go func() {
if err := grpcServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal().Err(err).Msg("unable to start grpc server")
}
}()

// <-sigs
<-sigs

// log.Info().Msg("caught SIGTERM, exiting")
// cancel()
log.Info().Msg("caught SIGTERM, exiting")
cancel()

// if err := grpcServer.Shutdown(ctx); err != nil {
// log.Error().Err(err).Msg("unable to stop grpc server")
// }
if err := grpcServer.Shutdown(ctx); err != nil {
log.Error().Err(err).Msg("unable to stop grpc server")
}

// log.Info().Msg("work done; exiting")
log.Info().Msg("work done; exiting")

// os.Exit(0)
fmt.Println("Hello, World!")
os.Exit(0)
}
7 changes: 2 additions & 5 deletions src/internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
package config

import (
"github.com/Golerplate/pkg/grpc"
"github.com/caarlos0/env/v8"
"github.com/rs/zerolog/log"
)

type Config struct {
GRPCServerConfig
grpc.GRPCServerConfig
GeneralConfig
}

type GeneralConfig struct {
Environment string `env:"ENVIRONMENT" envDefault:"local"`
}

type GRPCServerConfig struct {
Port uint16 `env:"GRPC_SERVER_PORT" envDefault:"50051"`
}

func GetServiceConfig() *Config {
var cfg Config
if err := env.Parse(&cfg); err != nil {
Expand Down
12 changes: 9 additions & 3 deletions src/internal/entity/user/v1/user.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package entity_user_v1

import "time"

type User struct {
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
IsAdmin bool `json:"is_admin"`
IsBanned bool `json:"is_banned"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

type CreateUserRequest struct {
Expand Down
24 changes: 12 additions & 12 deletions src/internal/handler/user/v1/init.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package handler_user_v1

// import (
// "github.com/Golerplate/contracts/generated/services/user/store/v1/storev1connect"
// "github.com/Golerplate/user-store-svc/src/internal/service"
// )
import (
"github.com/Golerplate/contracts/generated/services/user/store/v1/storev1connect"
"github.com/Golerplate/user-store-svc/src/internal/service"
)

// type handler struct {
// userStoreService service.UserStoreService
// }
type handler struct {
userStoreService service.UserStoreService
}

// func NewUserStoreServiceHandler(userStoreService service.UserStoreService) storev1connect.UserStoreServiceHandler {
// return &handler{
// userStoreService: userStoreService,
// }
// }
func NewUserStoreServiceHandler(userStoreService service.UserStoreService) storev1connect.UserStoreServiceHandler {
return &handler{
userStoreService: userStoreService,
}
}
47 changes: 47 additions & 0 deletions src/internal/handler/user/v1/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package handler_user_v1

import (
"context"
"errors"

userv1 "github.com/Golerplate/contracts/generated/services/user/store/v1"
"github.com/Golerplate/pkg/grpc"
entity_user_v1 "github.com/Golerplate/user-store-svc/src/internal/entity/user/v1"
connectgo "github.com/bufbuild/connect-go"
"github.com/golang/protobuf/ptypes/wrappers"
"google.golang.org/protobuf/types/known/timestamppb"
)

func (h *handler) CreateUser(ctx context.Context, c *connectgo.Request[userv1.CreateUserRequest]) (*connectgo.Response[userv1.CreateUserResponse], error) {

if c.Msg.GetUsername() == nil || c.Msg.GetUsername().GetValue() == "" {
return nil, connectgo.NewError(connectgo.CodeInvalidArgument, errors.New("invalid username"))
}
if c.Msg.GetEmail() == nil || c.Msg.GetEmail().GetValue() == "" {
return nil, connectgo.NewError(connectgo.CodeInvalidArgument, errors.New("invalid email"))
}
if c.Msg.GetPassword() == nil || c.Msg.GetPassword().GetValue() == "" {
return nil, connectgo.NewError(connectgo.CodeInvalidArgument, errors.New("invalid password"))
}

user, err := h.userStoreService.CreateUser(ctx, &entity_user_v1.CreateUserRequest{
Username: c.Msg.GetUsername().GetValue(),
Email: c.Msg.GetEmail().GetValue(),
Password: c.Msg.GetPassword().GetValue(),
})
if err != nil {
return nil, grpc.TranslateToGRPCError(ctx, err)
}

return connectgo.NewResponse(&userv1.CreateUserResponse{
User: &userv1.User{
Id: &wrappers.StringValue{Value: user.ID},
Username: &wrappers.StringValue{Value: user.Username},
Email: &wrappers.StringValue{Value: user.Email},
IsAdmin: &wrappers.BoolValue{Value: user.IsAdmin},
IsBanned: &wrappers.BoolValue{Value: user.IsBanned},
CreatedAt: &timestamppb.Timestamp{Seconds: int64(user.CreatedAt.Second()), Nanos: int32(user.CreatedAt.Nanosecond())},
UpdatedAt: &timestamppb.Timestamp{Seconds: int64(user.UpdatedAt.Second()), Nanos: int32(user.UpdatedAt.Nanosecond())},
},
}), nil
}
44 changes: 23 additions & 21 deletions src/internal/server/user/v1/server.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
package server_user_v1

// import (
// "net/http"
import (
"net/http"

// connectgo "github.com/bufbuild/connect-go"
// grpcreflect "github.com/bufbuild/connect-grpcreflect-go"
// connect_go_prometheus "github.com/easyCZ/connect-go-prometheus"
// )
"github.com/Golerplate/contracts/generated/services/servicesconnect"
"github.com/Golerplate/contracts/generated/services/user/store/v1/storev1connect"
handlers "github.com/Golerplate/pkg/grpc/handlers"
sharedmidlewares "github.com/Golerplate/pkg/grpc/interceptors"
connectgo "github.com/bufbuild/connect-go"
grpcreflect "github.com/bufbuild/connect-grpcreflect-go"
)

// func NewGRPCBuilder(
// chnlStoreServiceHandler storev1connect.ChnlStoreServiceHandler,
// ) *http.ServeMux {
// interceptorchain := append(sharedmidlewares.ServerDefaultChain(), connect_go_prometheus.NewInterceptor())
// interceptors := connectgo.WithInterceptors(interceptorchain...)
func NewGRPCBuilder(
userStoreServiceHandler storev1connect.UserStoreServiceHandler,
) *http.ServeMux {
interceptors := connectgo.WithInterceptors(sharedmidlewares.ServerDefaultChain()...)

// reflector := grpcreflect.NewStaticReflector(
// "services.user.store.v1.UserStoreService", "services.health.HealthService",
// )
reflector := grpcreflect.NewStaticReflector(
"services.user.store.v1.UserStoreSvc", "services.health.HealthService",
)

// mux := http.NewServeMux()
// mux.Handle(servicesconnect.NewHealthServiceHandler(handlers.NewHealthHandler()))
// mux.Handle(storev1connect.NewChnlStoreServiceHandler(chnlStoreServiceHandler, interceptors))
// mux.Handle(grpcreflect.NewHandlerV1(reflector))
// mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector))
mux := http.NewServeMux()
mux.Handle(servicesconnect.NewHealthServiceHandler(handlers.NewHealthHandler()))
mux.Handle(storev1connect.NewUserStoreServiceHandler(userStoreServiceHandler, interceptors))
mux.Handle(grpcreflect.NewHandlerV1(reflector))
mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector))

// return mux
// }
return mux
}

0 comments on commit a1e5f9b

Please sign in to comment.