From cb62e7e660810b699b5b6fae1d253979db877c41 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 21:51:45 +0700 Subject: [PATCH 01/11] feat: main init db, conf, net --- src/main.go | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/main.go b/src/main.go index 70b6c9a..0b4100e 100644 --- a/src/main.go +++ b/src/main.go @@ -1,5 +1,36 @@ package main +import ( + "fmt" + "net" + + "github.com/isd-sgcu/johnjud-backend/src/config" + "github.com/isd-sgcu/johnjud-backend/src/database" + "github.com/rs/zerolog/log" +) + func main() { - // Code + conf, err := config.LoadConfig() + if err != nil { + log.Fatal(). + Err(err). + Str("service", "backend load config"). + Msg("Failed to start service") + } + + db, err := database.InitPostgresDatabase(&conf.Database, conf.App.Debug) + if err != nil { + log.Fatal(). + Err(err). + Str("service", "backend database"). + Msg("Failed to start service") + } + + lis, err := net.Listen("tcp", fmt.Sprintf(":%v", conf.App.Port)) + if err != nil { + log.Fatal(). + Err(err). + Str("service", "backend server"). + Msg("Failed to start service") + } } From e0a450c313b8626889642e981571a82e7f71ed75 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:15:29 +0700 Subject: [PATCH 02/11] feat: config add file service --- config/config.example.yaml | 3 +++ src/config/config.go | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/config/config.example.yaml b/config/config.example.yaml index a413180..f4c5111 100644 --- a/config/config.example.yaml +++ b/config/config.example.yaml @@ -8,3 +8,6 @@ database: name: johnjud_db username: root password: root + +service: + file: localhost:3003 \ No newline at end of file diff --git a/src/config/config.go b/src/config/config.go index c526550..fc6876a 100644 --- a/src/config/config.go +++ b/src/config/config.go @@ -19,9 +19,14 @@ type App struct { Debug bool `mapstructure:"debug"` } +type Service struct { + File string `mapstructure:"file"` +} + type Config struct { App App `mapstructure:"app"` Database Database `mapstructure:"database"` + Service Service `mapstructure:"service"` } func LoadConfig() (config *Config, err error) { From c0c0c831d39b5de2e0cb565b2f540142be41c9f0 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:19:54 +0700 Subject: [PATCH 03/11] feat: service add proto.UnimplementedLikeServiceServer --- src/app/service/like/like.service.go | 1 + src/app/service/pet/pet.service.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/service/like/like.service.go b/src/app/service/like/like.service.go index 064558b..1d111fc 100644 --- a/src/app/service/like/like.service.go +++ b/src/app/service/like/like.service.go @@ -15,6 +15,7 @@ import ( ) type Service struct { + proto.UnimplementedLikeServiceServer repository IRepository } diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index 4b021b5..d71c292 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -19,6 +19,7 @@ import ( ) type Service struct { + proto.UnimplementedPetServiceServer repository IRepository imageService ImageService } @@ -36,7 +37,7 @@ type ImageService interface { } func NewService(repository IRepository, imageService ImageService) *Service { - return &Service{repository, imageService} + return &Service{repository: repository, imageService: imageService} } func (s *Service) Delete(ctx context.Context, req *proto.DeletePetRequest) (*proto.DeletePetResponse, error) { From f24b4cf3edc2991693f86cd6e0a49cf6049c5d59 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:20:28 +0700 Subject: [PATCH 04/11] feat: main graceful shutdown, repo, srv --- go.mod | 14 +----- go.sum | 4 ++ src/main.go | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 140 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 4afd1ea..ade5ec4 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ toolchain go1.21.5 require ( github.com/bxcodec/faker/v3 v3.8.1 github.com/google/uuid v1.5.0 - github.com/isd-sgcu/johnjud-go-proto v0.0.8 + github.com/isd-sgcu/johnjud-go-proto v0.0.9 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.31.0 github.com/spf13/viper v1.18.2 @@ -26,43 +26,33 @@ require ( github.com/stretchr/objx v0.5.0 // indirect golang.org/x/net v0.19.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect ) require ( github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/isd-sgcu/johnjud-go-proto v0.0.8 github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect - github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.4 - github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.16.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9366728..cc506c7 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/isd-sgcu/johnjud-go-proto v0.0.8 h1:nIQBZgK2OFVrLjVtpeDgwows8poA7LhsIVE4hlbBC1o= github.com/isd-sgcu/johnjud-go-proto v0.0.8/go.mod h1:HP0w9gC30b5WNnqeFBM9JJZud+pvyikz0+pGFSI/Wjw= +github.com/isd-sgcu/johnjud-go-proto v0.0.9 h1:cFfZ2JSpW0jg94Iv5zHQJGnoekj0eCQe42SJaTpnp3c= +github.com/isd-sgcu/johnjud-go-proto v0.0.9/go.mod h1:1OK6aiCgtXQiLhxp0r6iLEejYIRpckWQZDrCZ9Trbo4= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -109,6 +111,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/src/main.go b/src/main.go index 0b4100e..e23b1b4 100644 --- a/src/main.go +++ b/src/main.go @@ -1,36 +1,165 @@ package main import ( + "context" "fmt" "net" + "os" + "os/signal" + "sync" + "syscall" + "time" + likeRepo "github.com/isd-sgcu/johnjud-backend/src/app/repository/like" + petRepo "github.com/isd-sgcu/johnjud-backend/src/app/repository/pet" + imageSrv "github.com/isd-sgcu/johnjud-backend/src/app/service/image" + likeSrv "github.com/isd-sgcu/johnjud-backend/src/app/service/like" + petSrv "github.com/isd-sgcu/johnjud-backend/src/app/service/pet" "github.com/isd-sgcu/johnjud-backend/src/config" "github.com/isd-sgcu/johnjud-backend/src/database" + likePb "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/like/v1" + petPb "github.com/isd-sgcu/johnjud-go-proto/johnjud/backend/pet/v1" + imagePb "github.com/isd-sgcu/johnjud-go-proto/johnjud/file/image/v1" "github.com/rs/zerolog/log" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/health" + "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/reflection" ) +type operation func(ctx context.Context) error + +func gracefulShutdown(ctx context.Context, timeout time.Duration, ops map[string]operation) <-chan struct{} { + wait := make(chan struct{}) + go func() { + s := make(chan os.Signal, 1) + + signal.Notify(s, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) + sig := <-s + + log.Info(). + Str("service", "graceful shutdown"). + Msgf("got signal \"%v\" shutting down service", sig) + + timeoutFunc := time.AfterFunc(timeout, func() { + log.Error(). + Str("service", "graceful shutdown"). + Msgf("timeout %v ms has been elapsed, force exit", timeout.Milliseconds()) + os.Exit(0) + }) + + defer timeoutFunc.Stop() + + var wg sync.WaitGroup + + for key, op := range ops { + wg.Add(1) + innerOp := op + innerKey := key + go func() { + defer wg.Done() + + log.Info(). + Str("service", "graceful shutdown"). + Msgf("cleaning up: %v", innerKey) + if err := innerOp(ctx); err != nil { + log.Error(). + Str("service", "graceful shutdown"). + Err(err). + Msgf("%v: clean up failed: %v", innerKey, err.Error()) + return + } + + log.Info(). + Str("service", "graceful shutdown"). + Msgf("%v was shutdown gracefully", innerKey) + }() + } + + wg.Wait() + close(wait) + }() + + return wait +} + func main() { conf, err := config.LoadConfig() if err != nil { log.Fatal(). Err(err). - Str("service", "backend load config"). - Msg("Failed to start service") + Str("service", "backend"). + Msg("Failed to load config") } db, err := database.InitPostgresDatabase(&conf.Database, conf.App.Debug) if err != nil { log.Fatal(). Err(err). - Str("service", "backend database"). - Msg("Failed to start service") + Str("service", "backend"). + Msg("Failed to init postgres connection") + } + + fileConn, err := grpc.Dial(conf.Service.File, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + log.Fatal(). + Err(err). + Str("service", "johnjud-file"). + Msg("Cannot connect to service") } lis, err := net.Listen("tcp", fmt.Sprintf(":%v", conf.App.Port)) if err != nil { log.Fatal(). Err(err). - Str("service", "backend server"). + Str("service", "backend"). Msg("Failed to start service") } + + grpcServer := grpc.NewServer() + + likeRepo := likeRepo.NewRepository(db) + likeService := likeSrv.NewService(likeRepo) + + imageClient := imagePb.NewImageServiceClient(fileConn) + imageService := imageSrv.NewService(imageClient) + petRepo := petRepo.NewRepository(db) + petService := petSrv.NewService(petRepo, imageService) + + grpc_health_v1.RegisterHealthServer(grpcServer, health.NewServer()) + likePb.RegisterLikeServiceServer(grpcServer, likeService) + petPb.RegisterPetServiceServer(grpcServer, petService) + + reflection.Register(grpcServer) + go func() { + log.Info(). + Str("service", "backend"). + Msgf("JohnJud backend starting at port %v", conf.App.Port) + + if err := grpcServer.Serve(lis); err != nil { + log.Fatal(). + Err(err). + Str("service", "backend"). + Msg("Failed to start service") + } + }() + + wait := gracefulShutdown(context.Background(), 2*time.Second, map[string]operation{ + "server": func(ctx context.Context) error { + grpcServer.GracefulStop() + return nil + }, + }) + + <-wait + + grpcServer.GracefulStop() + log.Info(). + Str("service", "backend"). + Msg("Closing the listener") + lis.Close() + log.Info(). + Str("service", "backend"). + Msg("End the program") } From 9dfd0262690db418420f2b1528e01408d9e59201 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:28:48 +0700 Subject: [PATCH 05/11] fix: dokcer port typo --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 7c2ad2e..2ddebae 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -12,7 +12,7 @@ services: volumes: - postgres:/var/lib/postgresql/data ports: - - "5433:5432" + - "5432:5432" volumes: postgres: \ No newline at end of file From f568f0e6f248fa72ea32d77943ebc9c9d134382d Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:33:06 +0700 Subject: [PATCH 06/11] feat: postgres init table --- src/database/postgresql.connection.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/database/postgresql.connection.go b/src/database/postgresql.connection.go index 098b96b..95a0006 100644 --- a/src/database/postgresql.connection.go +++ b/src/database/postgresql.connection.go @@ -4,6 +4,8 @@ import ( "fmt" "strconv" + "github.com/isd-sgcu/johnjud-backend/src/app/model/like" + "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" "github.com/isd-sgcu/johnjud-backend/src/config" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -24,5 +26,10 @@ func InitPostgresDatabase(conf *config.Database, isDebug bool) (db *gorm.DB, err return nil, err } + err = db.AutoMigrate(&like.Like{}, &pet.Pet{}) + if err != nil { + return nil, err + } + return } From 92990f907b9bf390b6dc5236de906cfad9911161 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:39:41 +0700 Subject: [PATCH 07/11] fix: gorm postgres model --- src/app/model/common.model.go | 8 ++++---- src/app/model/user/user.model.go | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/app/model/common.model.go b/src/app/model/common.model.go index 682db1c..1ab9cd8 100644 --- a/src/app/model/common.model.go +++ b/src/app/model/common.model.go @@ -8,10 +8,10 @@ import ( ) type Base struct { - ID uuid.UUID `json:"id" gorm:"primaryKey;size:191"` - CreatedAt time.Time `json:"created_at" gorm:"type:datetime;autoCreateTime:nano"` - UpdatedAt time.Time `json:"updated_at" gorm:"type:datetime;autoUpdateTime:nano"` - DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index;type:datetime"` + ID uuid.UUID `json:"id" gorm:"primary_key"` + CreatedAt time.Time `json:"created_at" gorm:"type:timestamp;autoCreateTime:nano"` + UpdatedAt time.Time `json:"updated_at" gorm:"type:timestamp;autoUpdateTime:nano"` + DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index;type:timestamp"` } func (m *Base) BeforeCreate(_ *gorm.DB) error { diff --git a/src/app/model/user/user.model.go b/src/app/model/user/user.model.go index e93dae0..332db06 100644 --- a/src/app/model/user/user.model.go +++ b/src/app/model/user/user.model.go @@ -4,9 +4,9 @@ import "github.com/isd-sgcu/johnjud-backend/src/app/model" type User struct { model.Base - Email string `json:"email" gorm:"type:tinytext"` - Password string `json:"password" gorm:"type:tinytext"` - Firstname string `json:"firstname" gorm:"type:tinytext"` - Lastname string `json:"lastname" gorm:"type:tinytext"` - Role string `json:"role" gorm:"type:tinytext"` + Email string `json:"email" gorm:"tinytext"` + Password string `json:"password" gorm:"tinytext"` + Firstname string `json:"firstname" gorm:"tinytext"` + Lastname string `json:"lastname" gorm:"tinytext"` + Role string `json:"role" gorm:"tinytext"` } From 1b393778deb3236c7b113e74a385fc6bee57c4e8 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 22:39:53 +0700 Subject: [PATCH 08/11] fix: db init also make user table --- src/database/postgresql.connection.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/database/postgresql.connection.go b/src/database/postgresql.connection.go index 95a0006..8369137 100644 --- a/src/database/postgresql.connection.go +++ b/src/database/postgresql.connection.go @@ -6,6 +6,7 @@ import ( "github.com/isd-sgcu/johnjud-backend/src/app/model/like" "github.com/isd-sgcu/johnjud-backend/src/app/model/pet" + "github.com/isd-sgcu/johnjud-backend/src/app/model/user" "github.com/isd-sgcu/johnjud-backend/src/config" "gorm.io/driver/postgres" "gorm.io/gorm" @@ -26,7 +27,7 @@ func InitPostgresDatabase(conf *config.Database, isDebug bool) (db *gorm.DB, err return nil, err } - err = db.AutoMigrate(&like.Like{}, &pet.Pet{}) + err = db.AutoMigrate(&user.User{}, &like.Like{}, &pet.Pet{}) if err != nil { return nil, err } From c0d0177c5dc3e3618c3965e2cd3e54af5ec980de Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 23:25:25 +0700 Subject: [PATCH 09/11] feat: pet model add adoptBy --- src/app/model/pet/pet.model.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/model/pet/pet.model.go b/src/app/model/pet/pet.model.go index d6b916a..3c88a37 100644 --- a/src/app/model/pet/pet.model.go +++ b/src/app/model/pet/pet.model.go @@ -22,4 +22,5 @@ type Pet struct { Background string `json:"background" gorm:"tinytext"` Address string `json:"address" gorm:"tinytext"` Contact string `json:"contact" gorm:"tinytext"` + AdoptBy string `json:"adopt_by" gorm:"tinytext"` } From e4d0ee64a29e057e03332a53d394af944e24fbf3 Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Wed, 27 Dec 2023 23:28:12 +0700 Subject: [PATCH 10/11] feat: add adoptby in pet service --- src/app/service/pet/pet.service.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/service/pet/pet.service.go b/src/app/service/pet/pet.service.go index d71c292..f7f0748 100644 --- a/src/app/service/pet/pet.service.go +++ b/src/app/service/pet/pet.service.go @@ -139,7 +139,7 @@ func (s Service) FindOne(_ context.Context, req *proto.FindOnePetRequest) (res * func (s *Service) Create(_ context.Context, req *proto.CreatePetRequest) (res *proto.CreatePetResponse, err error) { raw, err := DtoToRaw(req.Pet) if err != nil { - return nil, status.Error(codes.Internal, "error converting dto to raw") + return nil, status.Error(codes.Internal, "error converting dto to raw: "+err.Error()) } imgUrls := []string{} @@ -183,6 +183,7 @@ func RawToDto(in *pet.Pet, imgUrl []string) *proto.Pet { Background: in.Background, Address: in.Address, Contact: in.Contact, + AdoptBy: in.AdoptBy, } } @@ -234,6 +235,7 @@ func DtoToRaw(in *proto.Pet) (res *pet.Pet, err error) { Background: in.Background, Address: in.Address, Contact: in.Contact, + AdoptBy: in.AdoptBy, }, nil } From d6ded3d8b731a0141574102b7f0bc4961950d92a Mon Sep 17 00:00:00 2001 From: Idhibhat Pankam Date: Thu, 28 Dec 2023 00:21:19 +0700 Subject: [PATCH 11/11] fix: config file port to 3004 --- config/config.example.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.example.yaml b/config/config.example.yaml index f4c5111..34bc114 100644 --- a/config/config.example.yaml +++ b/config/config.example.yaml @@ -10,4 +10,4 @@ database: password: root service: - file: localhost:3003 \ No newline at end of file + file: localhost:3004 \ No newline at end of file