From 96b994e252f41ff68921d5c891cafa5b353733e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDan=20V=2E=20Dragan?= Date: Tue, 25 Feb 2025 10:41:00 +0100 Subject: [PATCH] refactor: split and move main file to cmd and move logic to internal Split HTTP and gRPC servers' bootstrapping and running into separate commands, placed under the cmd folder. Move logic to the internal folder. Update imports, Makefile commands and gitignore. --- .gitignore | 4 +- Makefile | 17 +-- cmd/grpc/main.go | 56 +++++++++ cmd/http/main.go | 85 +++++++++++++ {gapi => internal/gapi}/logger.go | 0 .../gapi}/rpc_get_account_balance_changes.go | 8 +- {gapi => internal/gapi}/rpc_get_ledger.go | 7 +- .../gapi}/rpc_get_transaction.go | 5 +- {gapi => internal/gapi}/server.go | 5 +- {models => internal/models}/models.go | 0 {util => internal/util}/config.go | 0 {util => internal/util}/constants.go | 0 main.go | 117 ------------------ proto/balance_changes.proto | 2 +- proto/daily_ledger.proto | 2 +- proto/ledger.proto | 2 +- proto/rpc_get_balance_changes.proto | 2 +- proto/rpc_get_ledger.proto | 2 +- proto/rpc_get_transaction.proto | 2 +- proto/service_gatehub_data_api.proto | 2 +- proto/transaction.proto | 2 +- 21 files changed, 177 insertions(+), 143 deletions(-) create mode 100644 cmd/grpc/main.go create mode 100644 cmd/http/main.go rename {gapi => internal/gapi}/logger.go (100%) rename {gapi => internal/gapi}/rpc_get_account_balance_changes.go (93%) rename {gapi => internal/gapi}/rpc_get_ledger.go (98%) rename {gapi => internal/gapi}/rpc_get_transaction.go (94%) rename {gapi => internal/gapi}/server.go (92%) rename {models => internal/models}/models.go (100%) rename {util => internal/util}/config.go (100%) rename {util => internal/util}/constants.go (100%) delete mode 100644 main.go diff --git a/.gitignore b/.gitignore index 0e4fa2b..d242c6c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ doc/swagger/* -pb/* \ No newline at end of file +internal/pb/* + +.idea/ diff --git a/Makefile b/Makefile index 02492f6..ce198ab 100644 --- a/Makefile +++ b/Makefile @@ -13,15 +13,18 @@ init: # generate proto files proto: rm -rf pb doc/swagger && \ - mkdir pb && mkdir -p doc/swagger && \ - protoc --proto_path=proto --go_out=pb --go_opt=paths=source_relative \ - --go-grpc_out=pb --go-grpc_opt=paths=source_relative \ - --grpc-gateway_out=pb --grpc-gateway_opt=paths=source_relative \ + mkdir -p internal/pb && mkdir -p doc/swagger && \ + protoc --proto_path=proto --go_out=internal/pb --go_opt=paths=source_relative \ + --go-grpc_out=internal/pb --go-grpc_opt=paths=source_relative \ + --grpc-gateway_out=internal/pb --grpc-gateway_opt=paths=source_relative \ --openapiv2_out=doc/swagger --openapiv2_opt=allow_merge=true,merge_file_name=gatehub-data-api \ + --experimental_allow_proto3_optional \ proto/*.proto \ && \ - protoc-go-inject-tag -input="./pb/*.pb.go" + protoc-go-inject-tag -input="./internal/pb/*.pb.go" .PHONY: start -start: - go run main.go \ No newline at end of file +start: + go run cmd/grpc/main.go & \ + go run cmd/http/main.go & \ + wait diff --git a/cmd/grpc/main.go b/cmd/grpc/main.go new file mode 100644 index 0000000..e04fd45 --- /dev/null +++ b/cmd/grpc/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "net" + "os" + + "github.com/go-redis/redis" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" + + "github.com/GateHubNet/data-api-go/internal/gapi" + "github.com/GateHubNet/data-api-go/internal/pb" + "github.com/GateHubNet/data-api-go/internal/util" +) + +func main() { + config, err := util.LoadConfig(".") + if err != nil { + log.Fatal().Err(err).Msg("cannot load config") + } + + if config.Environment == "development" { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + } + + server, err := gapi.NewServer(config) + if err != nil { + log.Fatal().Err(err).Msg("cannot create server") + } + + defer server.Store.Close() + defer func(Cache *redis.ClusterClient) { + if err := Cache.Close(); err != nil { + log.Error().Err(err).Msg("cannot close cache") + } + }(server.Cache) + + grpcLogger := grpc.UnaryInterceptor(gapi.GrpcLogger) + grpcServer := grpc.NewServer(grpcLogger) + pb.RegisterGateHubDataAPIServer(grpcServer, server) + reflection.Register(grpcServer) + + listener, err := net.Listen("tcp", config.GRPCServerAddress) + if err != nil { + log.Fatal().Err(err).Msg("cannot create listener") + } + + log.Info().Msgf("gRPC server listening on %v", listener.Addr()) + + err = grpcServer.Serve(listener) + if err != nil { + log.Fatal().Err(err).Msg("cannot start gRPC server") + } +} diff --git a/cmd/http/main.go b/cmd/http/main.go new file mode 100644 index 0000000..5f328f6 --- /dev/null +++ b/cmd/http/main.go @@ -0,0 +1,85 @@ +package main + +import ( + "context" + "net" + "net/http" + "os" + "strconv" + + "github.com/go-redis/redis" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + "google.golang.org/protobuf/proto" + + "github.com/GateHubNet/data-api-go/internal/gapi" + "github.com/GateHubNet/data-api-go/internal/pb" + "github.com/GateHubNet/data-api-go/internal/util" +) + +func main() { + config, err := util.LoadConfig(".") + if err != nil { + log.Fatal().Err(err).Msg("cannot load config") + } + + if config.Environment == "development" { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + } + + server, err := gapi.NewServer(config) + if err != nil { + log.Fatal().Err(err).Msg("cannot create server") + } + + defer server.Store.Close() + defer func(Cache *redis.ClusterClient) { + if err := Cache.Close(); err != nil { + log.Error().Err(err).Msg("cannot close cache") + } + }(server.Cache) + + grpcMux := runtime.NewServeMux(runtime.WithForwardResponseOption(func(ctx context.Context, w http.ResponseWriter, m proto.Message) error { + md, ok := runtime.ServerMetadataFromContext(ctx) + if !ok { + return nil + } + + if vals := md.HeaderMD.Get(util.HttpCode); len(vals) > 0 { + code, err := strconv.Atoi(vals[0]) + if err != nil { + return err + } + // delete the headers to not expose any grpc-metadata in http response + delete(md.HeaderMD, util.HttpCode) + delete(w.Header(), "Grpc-Metadata-X-Http-Code") + w.WriteHeader(code) + } + + return nil + })) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err = pb.RegisterGateHubDataAPIHandlerServer(ctx, grpcMux, server) + if err != nil { + log.Fatal().Err(err).Msg("cannot register handler server") + } + + mux := http.NewServeMux() + mux.Handle("/", grpcMux) + + listener, err := net.Listen("tcp", config.HTTPServerAddress) + if err != nil { + log.Fatal().Err(err).Msg("cannot create HTTP listener") + } + + log.Info().Msgf("HTTP server listening on %s", listener.Addr().String()) + + err = http.Serve(listener, mux) + if err != nil { + log.Fatal().Err(err).Msg("cannot start HTTP server") + } +} diff --git a/gapi/logger.go b/internal/gapi/logger.go similarity index 100% rename from gapi/logger.go rename to internal/gapi/logger.go diff --git a/gapi/rpc_get_account_balance_changes.go b/internal/gapi/rpc_get_account_balance_changes.go similarity index 93% rename from gapi/rpc_get_account_balance_changes.go rename to internal/gapi/rpc_get_account_balance_changes.go index df318c5..f66479d 100644 --- a/gapi/rpc_get_account_balance_changes.go +++ b/internal/gapi/rpc_get_account_balance_changes.go @@ -2,13 +2,15 @@ package gapi import ( "context" - "github.com/GateHubNet/data-api-go/models" - "github.com/GateHubNet/data-api-go/pb" - "github.com/GateHubNet/data-api-go/util" + "github.com/rs/zerolog/log" "github.com/scylladb/gocqlx/v2/qb" "google.golang.org/grpc" "google.golang.org/grpc/metadata" + + "github.com/GateHubNet/data-api-go/internal/models" + "github.com/GateHubNet/data-api-go/internal/pb" + "github.com/GateHubNet/data-api-go/internal/util" ) func (server *Server) accountBalanceChangesResponseHelper(ctx context.Context, balanceChanges []*pb.BalanceChanges) *pb.GetAccountBalanceChangesResponse { diff --git a/gapi/rpc_get_ledger.go b/internal/gapi/rpc_get_ledger.go similarity index 98% rename from gapi/rpc_get_ledger.go rename to internal/gapi/rpc_get_ledger.go index eb846f6..a7c68b6 100644 --- a/gapi/rpc_get_ledger.go +++ b/internal/gapi/rpc_get_ledger.go @@ -7,14 +7,15 @@ import ( "strconv" "time" - "github.com/GateHubNet/data-api-go/models" - "github.com/GateHubNet/data-api-go/pb" - "github.com/GateHubNet/data-api-go/util" "github.com/rs/zerolog/log" "github.com/scylladb/gocqlx/v2/qb" "google.golang.org/grpc" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/proto" + + "github.com/GateHubNet/data-api-go/internal/models" + "github.com/GateHubNet/data-api-go/internal/pb" + "github.com/GateHubNet/data-api-go/internal/util" ) func (server *Server) getLedgerByIndex(ledgerIndex int64) (*pb.Ledger, error) { diff --git a/gapi/rpc_get_transaction.go b/internal/gapi/rpc_get_transaction.go similarity index 94% rename from gapi/rpc_get_transaction.go rename to internal/gapi/rpc_get_transaction.go index 1b162fd..aacdd3b 100644 --- a/gapi/rpc_get_transaction.go +++ b/internal/gapi/rpc_get_transaction.go @@ -3,12 +3,13 @@ package gapi import ( "context" - "github.com/GateHubNet/data-api-go/models" - "github.com/GateHubNet/data-api-go/pb" "github.com/rs/zerolog/log" "github.com/scylladb/gocqlx/v2/qb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + "github.com/GateHubNet/data-api-go/internal/models" + "github.com/GateHubNet/data-api-go/internal/pb" ) func (server *Server) GetTransactionByHash(transactionHash string) (*pb.Transaction, error) { diff --git a/gapi/server.go b/internal/gapi/server.go similarity index 92% rename from gapi/server.go rename to internal/gapi/server.go index dcdd820..c0b8f8d 100644 --- a/gapi/server.go +++ b/internal/gapi/server.go @@ -5,12 +5,13 @@ import ( "strings" "time" - "github.com/GateHubNet/data-api-go/pb" - "github.com/GateHubNet/data-api-go/util" "github.com/go-redis/redis" "github.com/gocql/gocql" "github.com/rs/zerolog/log" "github.com/scylladb/gocqlx/v2" + + "github.com/GateHubNet/data-api-go/internal/pb" + "github.com/GateHubNet/data-api-go/internal/util" ) // Server serves gRPC requests for our GateHub Data Api service. diff --git a/models/models.go b/internal/models/models.go similarity index 100% rename from models/models.go rename to internal/models/models.go diff --git a/util/config.go b/internal/util/config.go similarity index 100% rename from util/config.go rename to internal/util/config.go diff --git a/util/constants.go b/internal/util/constants.go similarity index 100% rename from util/constants.go rename to internal/util/constants.go diff --git a/main.go b/main.go deleted file mode 100644 index ba39774..0000000 --- a/main.go +++ /dev/null @@ -1,117 +0,0 @@ -package main - -import ( - "context" - "net" - "net/http" - "os" - "strconv" - - "google.golang.org/protobuf/proto" - - "github.com/GateHubNet/data-api-go/gapi" - "github.com/GateHubNet/data-api-go/pb" - "github.com/GateHubNet/data-api-go/util" - "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - "google.golang.org/grpc" - "google.golang.org/grpc/reflection" -) - -func httpResponseModifier(ctx context.Context, w http.ResponseWriter, p proto.Message) error { - md, ok := runtime.ServerMetadataFromContext(ctx) - if !ok { - return nil - } - - // set http status code - if vals := md.HeaderMD.Get("x-http-code"); len(vals) > 0 { - code, err := strconv.Atoi(vals[0]) - if err != nil { - return err - } - // delete the headers to not expose any grpc-metadata in http response - delete(md.HeaderMD, "x-http-code") - delete(w.Header(), "Grpc-Metadata-X-Http-Code") - w.WriteHeader(code) - } - - return nil -} - -func main() { - config, err := util.LoadConfig(".") - if err != nil { - log.Fatal().Err(err).Msg("cannot load config") - } - - if config.Environment == "development" { - log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) - } - - go runGatewayServer(config) - runGrpcServer(config) -} - -func runGrpcServer(config util.Config) { - server, err := gapi.NewServer(config) - if err != nil { - log.Fatal().Err(err).Msg("cannot create server") - } - - defer server.Store.Close() - //TODO: handle error ... this actually doesnt matter because if this functions ends, server should also end - defer server.Cache.Close() - - grpcLogger := grpc.UnaryInterceptor(gapi.GrpcLogger) - grpcServer := grpc.NewServer(grpcLogger) - pb.RegisterGateHubDataAPIServer(grpcServer, server) - reflection.Register(grpcServer) - - listener, err := net.Listen("tcp", config.GRPCServerAddress) - if err != nil { - log.Fatal().Err(err).Msg("cannot create grpc listener") - } - - log.Info().Msgf("start gRPC server at %s", listener.Addr().String()) - err = grpcServer.Serve(listener) - if err != nil { - log.Fatal().Err(err).Msg("cannot start gRPC server") - } -} - -func runGatewayServer(config util.Config) { - server, err := gapi.NewServer(config) - if err != nil { - log.Fatal().Err(err).Msg("cannot create server") - } - - defer server.Store.Close() - //TODO: handle error ... this actually doesnt matter because if this functions ends, server should also end - defer server.Cache.Close() - - grpcMux := runtime.NewServeMux(runtime.WithForwardResponseOption(httpResponseModifier)) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - err = pb.RegisterGateHubDataAPIHandlerServer(ctx, grpcMux, server) - if err != nil { - log.Fatal().Err(err).Msg("cannot register handler server") - } - - mux := http.NewServeMux() - mux.Handle("/", grpcMux) - - listener, err := net.Listen("tcp", config.HTTPServerAddress) - if err != nil { - log.Fatal().Err(err).Msg("cannot create HTTP listener") - } - - log.Info().Msgf("start HTTP server at %s", listener.Addr().String()) - err = http.Serve(listener, mux) - if err != nil { - log.Fatal().Err(err).Msg("cannot start HTTP server") - } -} diff --git a/proto/balance_changes.proto b/proto/balance_changes.proto index d85f8c3..d300f0d 100644 --- a/proto/balance_changes.proto +++ b/proto/balance_changes.proto @@ -24,7 +24,7 @@ syntax = "proto3"; package proto; -option go_package="github.com/GateHubNet/data-api-go/pb"; +option go_package="github.com/GateHubNet/data-api-go/internal/pb"; message BalanceChanges { /* diff --git a/proto/daily_ledger.proto b/proto/daily_ledger.proto index 868f4e7..d3437c1 100644 --- a/proto/daily_ledger.proto +++ b/proto/daily_ledger.proto @@ -24,7 +24,7 @@ syntax = "proto3"; package proto; -option go_package="github.com/GateHubNet/data-api-go/pb"; +option go_package="github.com/GateHubNet/data-api-go/internal/pb"; message DailyLedger { /* diff --git a/proto/ledger.proto b/proto/ledger.proto index bbde93a..07c9926 100644 --- a/proto/ledger.proto +++ b/proto/ledger.proto @@ -24,7 +24,7 @@ syntax = "proto3"; package proto; -option go_package="github.com/GateHubNet/data-api-go/pb"; +option go_package="github.com/GateHubNet/data-api-go/internal/pb"; //import "google/protobuf/any.proto"; import "transaction.proto"; diff --git a/proto/rpc_get_balance_changes.proto b/proto/rpc_get_balance_changes.proto index 3c30f9c..89fc3f4 100644 --- a/proto/rpc_get_balance_changes.proto +++ b/proto/rpc_get_balance_changes.proto @@ -24,7 +24,7 @@ syntax = "proto3"; package proto; -option go_package="github.com/GateHubNet/data-api-go/pb"; +option go_package="github.com/GateHubNet/data-api-go/internal/pb"; import "balance_changes.proto"; import "protoc-gen-openapiv2/options/annotations.proto"; diff --git a/proto/rpc_get_ledger.proto b/proto/rpc_get_ledger.proto index 6b9e31e..fd08fad 100644 --- a/proto/rpc_get_ledger.proto +++ b/proto/rpc_get_ledger.proto @@ -24,7 +24,7 @@ syntax = "proto3"; package proto; -option go_package="github.com/GateHubNet/data-api-go/pb"; +option go_package="github.com/GateHubNet/data-api-go/internal/pb"; import "ledger.proto"; import "protoc-gen-openapiv2/options/annotations.proto"; diff --git a/proto/rpc_get_transaction.proto b/proto/rpc_get_transaction.proto index 8907db9..b17ba37 100644 --- a/proto/rpc_get_transaction.proto +++ b/proto/rpc_get_transaction.proto @@ -24,7 +24,7 @@ syntax = "proto3"; package proto; -option go_package="github.com/GateHubNet/data-api-go/pb"; +option go_package="github.com/GateHubNet/data-api-go/internal/pb"; import "transaction.proto"; import "protoc-gen-openapiv2/options/annotations.proto"; diff --git a/proto/service_gatehub_data_api.proto b/proto/service_gatehub_data_api.proto index 409eab9..68a5341 100644 --- a/proto/service_gatehub_data_api.proto +++ b/proto/service_gatehub_data_api.proto @@ -30,7 +30,7 @@ import "rpc_get_balance_changes.proto"; import "google/api/annotations.proto"; import "protoc-gen-openapiv2/options/annotations.proto"; -option go_package="github.com/GateHubNet/data-api-go/pb"; +option go_package="github.com/GateHubNet/data-api-go/internal/pb"; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { info: { diff --git a/proto/transaction.proto b/proto/transaction.proto index ccd3c1b..a484417 100644 --- a/proto/transaction.proto +++ b/proto/transaction.proto @@ -24,7 +24,7 @@ syntax = "proto3"; package proto; -option go_package="github.com/GateHubNet/data-api-go/pb"; +option go_package="github.com/GateHubNet/data-api-go/internal/pb"; message Transaction { /*