From 80fe136a42efa03e4fa2e8cfb501d016d0f4c456 Mon Sep 17 00:00:00 2001 From: varnit-goyal_navi Date: Tue, 23 Jul 2024 17:55:23 +0530 Subject: [PATCH 1/6] TP-55555 | crud ingestor --- .../202310201651_initial-migration.up.sql | 1 + go.mod | 1 + internal/database/product.go | 11 +++++ internal/dependencies/dependencies.go | 43 ++++++++++++++++--- internal/transport/handler/product.go | 32 ++++++++++++++ internal/transport/router/product.go | 11 +++++ internal/transport/server.go | 4 +- models/db/Release.go | 9 ++++ models/db/SourceMap.go | 9 ++++ models/db/product.go | 9 ++++ models/db/roles.go | 10 +++++ 11 files changed, 133 insertions(+), 7 deletions(-) create mode 100644 internal/database/product.go create mode 100644 internal/transport/handler/product.go create mode 100644 internal/transport/router/product.go create mode 100644 models/db/Release.go create mode 100644 models/db/SourceMap.go create mode 100644 models/db/product.go create mode 100644 models/db/roles.go diff --git a/db/migrations/202310201651_initial-migration.up.sql b/db/migrations/202310201651_initial-migration.up.sql index e69de29..faebb4b 100644 --- a/db/migrations/202310201651_initial-migration.up.sql +++ b/db/migrations/202310201651_initial-migration.up.sql @@ -0,0 +1 @@ +create database cybertron_dev; diff --git a/go.mod b/go.mod index 02c2346..aa409d6 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.15.5 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect diff --git a/internal/database/product.go b/internal/database/product.go new file mode 100644 index 0000000..faef203 --- /dev/null +++ b/internal/database/product.go @@ -0,0 +1,11 @@ +package database + +import ( + "cybertron/models/db" + "gorm.io/gorm" +) + +func InitProductRepository(dbClient *gorm.DB) *gorm.DB { + dbClient.AutoMigrate(&db.Product{}) + return dbClient +} diff --git a/internal/dependencies/dependencies.go b/internal/dependencies/dependencies.go index 5d27c4b..ba69333 100644 --- a/internal/dependencies/dependencies.go +++ b/internal/dependencies/dependencies.go @@ -1,27 +1,45 @@ package dependencies import ( + "cybertron/internal/database" + "cybertron/internal/transport/handler" + "cybertron/pkg/db" "cybertron/pkg/log" "go.uber.org/zap" "gorm.io/gorm" ) type Dependencies struct { - Service *Service - DBClient *gorm.DB - Logger *zap.Logger + Service *Service + DBClient *gorm.DB + Logger *zap.Logger + Handler *Handler + Repositories *Repositories } type Service struct { // Add your service here } +type Handler struct { + ProductHandler *handler.ProductHandler +} + +type Repositories struct { + ProductRepository *gorm.DB +} + func InitDependencies() *Dependencies { services := initServices() + dbClient := db.NewDBClient() + handlers := initHandlers(dbClient) + repositories := initRepositories(dbClient) return &Dependencies{ - Service: services, - //DBClient: db.NewDBClient(), - Logger: log.Log.GetLog(), + Service: services, + DBClient: dbClient, + Logger: log.Log.GetLog(), + Handler: handlers, + Repositories: repositories, } } @@ -30,3 +48,16 @@ func initServices() *Service { // Add your service here } } + +func initRepositories(dbClient *gorm.DB) *Repositories { + return &Repositories{ + ProductRepository: database.InitProductRepository(dbClient), + } +} + +func initHandlers(dbClient *gorm.DB) *Handler { + productHandler := handler.NewProductHandler(dbClient) + return &Handler{ + ProductHandler: productHandler, + } +} diff --git a/internal/transport/handler/product.go b/internal/transport/handler/product.go new file mode 100644 index 0000000..399cb3c --- /dev/null +++ b/internal/transport/handler/product.go @@ -0,0 +1,32 @@ +package handler + +import ( + "cybertron/models/db" + "github.com/gin-gonic/gin" + "gorm.io/gorm" + "net/http" +) + +type ProductHandler struct { + dbClient *gorm.DB +} + +func (h *ProductHandler) ProductCreate(c *gin.Context) { + h.dbClient.Create(&db.Product{ProductReferenceId: "1", Name: "name"}) + c.JSON(http.StatusOK, gin.H{ + "message": "create product", + }) +} + +func (h *ProductHandler) ProductGet(c *gin.Context) { + var product db.Product + h.dbClient.First(&product, 1) + c.JSON(http.StatusOK, gin.H{ + "message": product, + }) +} +func NewProductHandler(dbClient *gorm.DB) *ProductHandler { + return &ProductHandler{ + dbClient: dbClient, + } +} diff --git a/internal/transport/router/product.go b/internal/transport/router/product.go new file mode 100644 index 0000000..049c5b1 --- /dev/null +++ b/internal/transport/router/product.go @@ -0,0 +1,11 @@ +package router + +import ( + "cybertron/internal/dependencies" + "github.com/gin-gonic/gin" +) + +func ProductRouter(r *gin.Engine, dep *dependencies.Dependencies) { + r.GET("/product", dep.Handler.ProductHandler.ProductCreate) + r.GET("/productGet", dep.Handler.ProductHandler.ProductGet) +} diff --git a/internal/transport/server.go b/internal/transport/server.go index 7adb827..85e445c 100644 --- a/internal/transport/server.go +++ b/internal/transport/server.go @@ -6,6 +6,7 @@ import ( "os" "os/signal" "syscall" + "time" "cybertron/configs" "cybertron/internal/dependencies" @@ -29,10 +30,11 @@ func NewServer(dep *dependencies.Dependencies) *Server { func (s *Server) router() { router.ReadinessRouter(s.gin) + router.ProductRouter(s.gin, s.dependencies) } func (s *Server) Start() { - s.gin.Use(ginzap.RecoveryWithZap(s.dependencies.Logger, true)) + s.gin.Use(ginzap.Ginzap(s.dependencies.Logger, time.RFC3339, false)) s.router() port := configs.GetPort() diff --git a/models/db/Release.go b/models/db/Release.go new file mode 100644 index 0000000..8a6db3f --- /dev/null +++ b/models/db/Release.go @@ -0,0 +1,9 @@ +package db + +import "gorm.io/gorm" + +type Release struct { + gorm.Model + ProductReferenceId string `gorm:"primaryKey"` + ReleaseVersion string `gorm:"column:name"` +} diff --git a/models/db/SourceMap.go b/models/db/SourceMap.go new file mode 100644 index 0000000..f806728 --- /dev/null +++ b/models/db/SourceMap.go @@ -0,0 +1,9 @@ +package db + +import "gorm.io/gorm" + +type SourceMap struct { + gorm.Model + ReleaseReferenceId string `gorm:"primaryKey"` + SourceMapZipUrl string `gorm:"column:name"` +} diff --git a/models/db/product.go b/models/db/product.go new file mode 100644 index 0000000..c962822 --- /dev/null +++ b/models/db/product.go @@ -0,0 +1,9 @@ +package db + +import "gorm.io/gorm" + +type Product struct { + gorm.Model + ProductReferenceId string `gorm:"primaryKey"` + Name string `gorm:"column:name"` +} diff --git a/models/db/roles.go b/models/db/roles.go new file mode 100644 index 0000000..0d944e2 --- /dev/null +++ b/models/db/roles.go @@ -0,0 +1,10 @@ +package db + +import "gorm.io/gorm" + +type Roles struct { + gorm.Model + ProductReferenceId string `gorm:"primaryKey"` + Role string `gorm:"column:name"` +} + From 095288760664ca960edbe24d352c7039e617b803 Mon Sep 17 00:00:00 2001 From: Lokesh Dugar Date: Wed, 24 Jul 2024 12:30:35 +0530 Subject: [PATCH 2/6] TP-55555 | Project handler --- go.mod | 2 +- internal/database/product.go | 11 ----- internal/database/project.go | 11 +++++ internal/dependencies/dependencies.go | 10 ++--- internal/transport/handler/product.go | 32 --------------- internal/transport/handler/project.go | 53 +++++++++++++++++++++++++ internal/transport/handler/readiness.go | 3 +- internal/transport/router/product.go | 11 ----- internal/transport/router/project.go | 16 ++++++++ internal/transport/server.go | 2 +- models/db/Release.go | 2 +- models/db/product.go | 9 ----- models/db/project.go | 13 ++++++ models/db/roles.go | 3 +- 14 files changed, 104 insertions(+), 74 deletions(-) delete mode 100644 internal/database/product.go create mode 100644 internal/database/project.go delete mode 100644 internal/transport/handler/product.go create mode 100644 internal/transport/handler/project.go delete mode 100644 internal/transport/router/product.go create mode 100644 internal/transport/router/project.go delete mode 100644 models/db/product.go create mode 100644 models/db/project.go diff --git a/go.mod b/go.mod index aa409d6..faeb7d0 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/gin-contrib/zap v0.2.0 github.com/gin-gonic/gin v1.9.1 github.com/golang-migrate/migrate/v4 v4.17.1 + github.com/google/uuid v1.4.0 github.com/prometheus/client_golang v1.19.1 github.com/spf13/cobra v1.7.0 github.com/spf13/viper v1.17.0 @@ -28,7 +29,6 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.15.5 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect diff --git a/internal/database/product.go b/internal/database/product.go deleted file mode 100644 index faef203..0000000 --- a/internal/database/product.go +++ /dev/null @@ -1,11 +0,0 @@ -package database - -import ( - "cybertron/models/db" - "gorm.io/gorm" -) - -func InitProductRepository(dbClient *gorm.DB) *gorm.DB { - dbClient.AutoMigrate(&db.Product{}) - return dbClient -} diff --git a/internal/database/project.go b/internal/database/project.go new file mode 100644 index 0000000..32a5ca6 --- /dev/null +++ b/internal/database/project.go @@ -0,0 +1,11 @@ +package database + +import ( + "cybertron/models/db" + "gorm.io/gorm" +) + +func InitProjectRepository(dbClient *gorm.DB) *gorm.DB { + dbClient.AutoMigrate(&db.Project{}) + return dbClient +} diff --git a/internal/dependencies/dependencies.go b/internal/dependencies/dependencies.go index ba69333..04a87aa 100644 --- a/internal/dependencies/dependencies.go +++ b/internal/dependencies/dependencies.go @@ -22,11 +22,11 @@ type Service struct { } type Handler struct { - ProductHandler *handler.ProductHandler + ProjectHandler *handler.ProjectHandler } type Repositories struct { - ProductRepository *gorm.DB + ProjectRepository *gorm.DB } func InitDependencies() *Dependencies { @@ -51,13 +51,13 @@ func initServices() *Service { func initRepositories(dbClient *gorm.DB) *Repositories { return &Repositories{ - ProductRepository: database.InitProductRepository(dbClient), + ProjectRepository: database.InitProjectRepository(dbClient), } } func initHandlers(dbClient *gorm.DB) *Handler { - productHandler := handler.NewProductHandler(dbClient) + projectHandler := handler.NewProjectHandler(dbClient) return &Handler{ - ProductHandler: productHandler, + ProjectHandler: projectHandler, } } diff --git a/internal/transport/handler/product.go b/internal/transport/handler/product.go deleted file mode 100644 index 399cb3c..0000000 --- a/internal/transport/handler/product.go +++ /dev/null @@ -1,32 +0,0 @@ -package handler - -import ( - "cybertron/models/db" - "github.com/gin-gonic/gin" - "gorm.io/gorm" - "net/http" -) - -type ProductHandler struct { - dbClient *gorm.DB -} - -func (h *ProductHandler) ProductCreate(c *gin.Context) { - h.dbClient.Create(&db.Product{ProductReferenceId: "1", Name: "name"}) - c.JSON(http.StatusOK, gin.H{ - "message": "create product", - }) -} - -func (h *ProductHandler) ProductGet(c *gin.Context) { - var product db.Product - h.dbClient.First(&product, 1) - c.JSON(http.StatusOK, gin.H{ - "message": product, - }) -} -func NewProductHandler(dbClient *gorm.DB) *ProductHandler { - return &ProductHandler{ - dbClient: dbClient, - } -} diff --git a/internal/transport/handler/project.go b/internal/transport/handler/project.go new file mode 100644 index 0000000..5beb2d5 --- /dev/null +++ b/internal/transport/handler/project.go @@ -0,0 +1,53 @@ +package handler + +import ( + "cybertron/models/db" + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "gorm.io/gorm" + "net/http" +) + +type ProjectHandler struct { + dbClient *gorm.DB +} + +type ProjectBody struct { + Name string `json:"name" binding:"required"` + Team string `json:"team" binding:"required"` +} + +func (h *ProjectHandler) ProjectCreate(c *gin.Context) { + var projectBody ProjectBody + if err := c.BindJSON(&projectBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "message": "Invalid Request", + }) + return + } + + // Write to database + h.dbClient.Create(&db.Project{ + ProjectReferenceId: uuid.New(), + Name: projectBody.Name, + Team: projectBody.Team, + }) + + c.JSON(http.StatusOK, gin.H{ + "message": "Project created", + }) +} + +func (h *ProjectHandler) ProjectGet(c *gin.Context) { + var project db.Project + h.dbClient.First(&project, 1) + c.JSON(http.StatusOK, gin.H{ + "message": project, + }) +} + +func NewProjectHandler(dbClient *gorm.DB) *ProjectHandler { + return &ProjectHandler{ + dbClient: dbClient, + } +} diff --git a/internal/transport/handler/readiness.go b/internal/transport/handler/readiness.go index 737a19f..7913b7c 100644 --- a/internal/transport/handler/readiness.go +++ b/internal/transport/handler/readiness.go @@ -6,7 +6,8 @@ import ( "github.com/gin-gonic/gin" ) -type HealthCheckHandler struct{} +type HealthCheckHandler struct { +} func (h *HealthCheckHandler) Readiness(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ diff --git a/internal/transport/router/product.go b/internal/transport/router/product.go deleted file mode 100644 index 049c5b1..0000000 --- a/internal/transport/router/product.go +++ /dev/null @@ -1,11 +0,0 @@ -package router - -import ( - "cybertron/internal/dependencies" - "github.com/gin-gonic/gin" -) - -func ProductRouter(r *gin.Engine, dep *dependencies.Dependencies) { - r.GET("/product", dep.Handler.ProductHandler.ProductCreate) - r.GET("/productGet", dep.Handler.ProductHandler.ProductGet) -} diff --git a/internal/transport/router/project.go b/internal/transport/router/project.go new file mode 100644 index 0000000..f925efe --- /dev/null +++ b/internal/transport/router/project.go @@ -0,0 +1,16 @@ +package router + +import ( + "cybertron/internal/dependencies" + "cybertron/internal/transport/handler" + "github.com/gin-gonic/gin" +) + +func ProjectRouter(r *gin.Engine, dep *dependencies.Dependencies) { + projectHandler := handler.NewProjectHandler(dep.DBClient) + projectRouterGroup := r.Group("/api/v1") + { + projectRouterGroup.POST("/project", projectHandler.ProjectCreate) + projectRouterGroup.GET("/project", projectHandler.ProjectGet) // TODO: Can make this paginated in future + } +} diff --git a/internal/transport/server.go b/internal/transport/server.go index 85e445c..5b3e015 100644 --- a/internal/transport/server.go +++ b/internal/transport/server.go @@ -30,7 +30,7 @@ func NewServer(dep *dependencies.Dependencies) *Server { func (s *Server) router() { router.ReadinessRouter(s.gin) - router.ProductRouter(s.gin, s.dependencies) + router.ProjectRouter(s.gin, s.dependencies) } func (s *Server) Start() { diff --git a/models/db/Release.go b/models/db/Release.go index 8a6db3f..43eab6d 100644 --- a/models/db/Release.go +++ b/models/db/Release.go @@ -4,6 +4,6 @@ import "gorm.io/gorm" type Release struct { gorm.Model - ProductReferenceId string `gorm:"primaryKey"` + ProjectReferenceId string `gorm:"primaryKey"` ReleaseVersion string `gorm:"column:name"` } diff --git a/models/db/product.go b/models/db/product.go deleted file mode 100644 index c962822..0000000 --- a/models/db/product.go +++ /dev/null @@ -1,9 +0,0 @@ -package db - -import "gorm.io/gorm" - -type Product struct { - gorm.Model - ProductReferenceId string `gorm:"primaryKey"` - Name string `gorm:"column:name"` -} diff --git a/models/db/project.go b/models/db/project.go new file mode 100644 index 0000000..d91764c --- /dev/null +++ b/models/db/project.go @@ -0,0 +1,13 @@ +package db + +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) + +type Project struct { + gorm.Model + ProjectReferenceId uuid.UUID `gorm:"primaryKey"` + Name string `gorm:"column:name;unique"` + Team string +} diff --git a/models/db/roles.go b/models/db/roles.go index 0d944e2..527caf7 100644 --- a/models/db/roles.go +++ b/models/db/roles.go @@ -4,7 +4,6 @@ import "gorm.io/gorm" type Roles struct { gorm.Model - ProductReferenceId string `gorm:"primaryKey"` + ProjectReferenceId string `gorm:"primaryKey"` Role string `gorm:"column:name"` } - From e02d17b85ff3d8b36851e53303675cae4d1049bf Mon Sep 17 00:00:00 2001 From: Lokesh Dugar Date: Wed, 24 Jul 2024 14:59:27 +0530 Subject: [PATCH 3/6] TP-55555 | Get all the projects --- internal/transport/handler/project.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/internal/transport/handler/project.go b/internal/transport/handler/project.go index 5beb2d5..99514ec 100644 --- a/internal/transport/handler/project.go +++ b/internal/transport/handler/project.go @@ -39,11 +39,15 @@ func (h *ProjectHandler) ProjectCreate(c *gin.Context) { } func (h *ProjectHandler) ProjectGet(c *gin.Context) { - var project db.Project - h.dbClient.First(&project, 1) - c.JSON(http.StatusOK, gin.H{ - "message": project, - }) + var projects []db.Project + h.dbClient.Find(&projects) + + if result := h.dbClient.Find(&projects); result.Error != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) + return + } + + c.JSON(http.StatusOK, projects) } func NewProjectHandler(dbClient *gorm.DB) *ProjectHandler { From a5805107422db91e747a8de346d944760bf7297b Mon Sep 17 00:00:00 2001 From: Lokesh Dugar Date: Wed, 24 Jul 2024 15:46:50 +0530 Subject: [PATCH 4/6] TP-55555 | Releases handler added --- internal/dependencies/dependencies.go | 8 +++-- internal/transport/handler/releases.go | 49 ++++++++++++++++++++++++++ internal/transport/router/releases.go | 15 ++++++++ internal/transport/server.go | 1 + models/db/Release.go | 13 +++++-- models/db/project.go | 13 ++++--- 6 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 internal/transport/handler/releases.go create mode 100644 internal/transport/router/releases.go diff --git a/internal/dependencies/dependencies.go b/internal/dependencies/dependencies.go index 04a87aa..8ed43f5 100644 --- a/internal/dependencies/dependencies.go +++ b/internal/dependencies/dependencies.go @@ -22,7 +22,8 @@ type Service struct { } type Handler struct { - ProjectHandler *handler.ProjectHandler + ProjectHandler *handler.ProjectHandler + ReleasesHandler *handler.ReleasesHandler } type Repositories struct { @@ -57,7 +58,10 @@ func initRepositories(dbClient *gorm.DB) *Repositories { func initHandlers(dbClient *gorm.DB) *Handler { projectHandler := handler.NewProjectHandler(dbClient) + releasesHandler := handler.NewReleaseHandler(dbClient) + return &Handler{ - ProjectHandler: projectHandler, + ProjectHandler: projectHandler, + ReleasesHandler: releasesHandler, } } diff --git a/internal/transport/handler/releases.go b/internal/transport/handler/releases.go new file mode 100644 index 0000000..47704aa --- /dev/null +++ b/internal/transport/handler/releases.go @@ -0,0 +1,49 @@ +package handler + +import ( + "cybertron/models/db" + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "gorm.io/gorm" + "net/http" +) + +type ReleasesHandler struct { + dbClient *gorm.DB +} + +type ReleaseBody struct { + ProjectId string `json:"project_id" binding:"required"` + Version string `json:"version" binding:"required"` +} + +func (h *ReleasesHandler) AddRelease(c *gin.Context) { + var releaseBody ReleaseBody + if err := c.BindJSON(&releaseBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "message": "Invalid Request", + }) + return + } + + releaseToBeAdded := db.Release{ + ReleaseId: uuid.New(), + ProjectReferenceId: releaseBody.ProjectId, + ReleaseVersion: releaseBody.Version, + } + + if result := h.dbClient.Create(&releaseToBeAdded); result.Error != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "Release added successfully", + }) +} + +func NewReleaseHandler(dbClient *gorm.DB) *ReleasesHandler { + return &ReleasesHandler{ + dbClient: dbClient, + } +} diff --git a/internal/transport/router/releases.go b/internal/transport/router/releases.go new file mode 100644 index 0000000..1f8f160 --- /dev/null +++ b/internal/transport/router/releases.go @@ -0,0 +1,15 @@ +package router + +import ( + "cybertron/internal/dependencies" + "cybertron/internal/transport/handler" + "github.com/gin-gonic/gin" +) + +func ReleasesRouter(r *gin.Engine, dep *dependencies.Dependencies) { + releasesHandler := handler.NewReleaseHandler(dep.DBClient) + releasesGroup := r.Group("/api/v1") + { + releasesGroup.POST("/release", releasesHandler.AddRelease) + } +} diff --git a/internal/transport/server.go b/internal/transport/server.go index 5b3e015..b6b9792 100644 --- a/internal/transport/server.go +++ b/internal/transport/server.go @@ -31,6 +31,7 @@ func NewServer(dep *dependencies.Dependencies) *Server { func (s *Server) router() { router.ReadinessRouter(s.gin) router.ProjectRouter(s.gin, s.dependencies) + router.ReleasesRouter(s.gin, s.dependencies) } func (s *Server) Start() { diff --git a/models/db/Release.go b/models/db/Release.go index 43eab6d..e4d0c26 100644 --- a/models/db/Release.go +++ b/models/db/Release.go @@ -1,9 +1,16 @@ package db -import "gorm.io/gorm" +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) type Release struct { gorm.Model - ProjectReferenceId string `gorm:"primaryKey"` - ReleaseVersion string `gorm:"column:name"` + ReleaseId uuid.UUID `gorm:"primaryKey"` + ProjectReferenceId string + ReleaseVersion string `gorm:"unique"` + SourceMapUrl string // TODO: Check id required + ProjectID string + Project Project `gorm:"foreignKey:ProjectID"` } diff --git a/models/db/project.go b/models/db/project.go index d91764c..b68a527 100644 --- a/models/db/project.go +++ b/models/db/project.go @@ -2,12 +2,15 @@ package db import ( "github.com/google/uuid" - "gorm.io/gorm" + "time" ) type Project struct { - gorm.Model - ProjectReferenceId uuid.UUID `gorm:"primaryKey"` - Name string `gorm:"column:name;unique"` - Team string + ID int `json:"id"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt time.Time `json:"deletedAt"` + ProjectReferenceId uuid.UUID `json:"projectReferenceId" gorm:"primaryKey"` + Name string `json:"name" gorm:"unique"` + Team string `json:"team"` } From d95a639e93bf7cb133568b3dbde275b2d3de5851 Mon Sep 17 00:00:00 2001 From: Lokesh Dugar Date: Sat, 27 Jul 2024 17:02:42 +0530 Subject: [PATCH 5/6] TP-55555 | Release handler --- internal/database/project.go | 5 +++++ internal/dependencies/dependencies.go | 2 ++ models/db/Release.go | 16 ---------------- models/db/release.go | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 16 deletions(-) delete mode 100644 models/db/Release.go create mode 100644 models/db/release.go diff --git a/internal/database/project.go b/internal/database/project.go index 32a5ca6..3e0bed2 100644 --- a/internal/database/project.go +++ b/internal/database/project.go @@ -9,3 +9,8 @@ func InitProjectRepository(dbClient *gorm.DB) *gorm.DB { dbClient.AutoMigrate(&db.Project{}) return dbClient } + +func InitReleaseRepository(dbClient *gorm.DB) *gorm.DB { + dbClient.AutoMigrate(&db.Release{}) + return dbClient +} diff --git a/internal/dependencies/dependencies.go b/internal/dependencies/dependencies.go index 8ed43f5..eb2b06f 100644 --- a/internal/dependencies/dependencies.go +++ b/internal/dependencies/dependencies.go @@ -28,6 +28,7 @@ type Handler struct { type Repositories struct { ProjectRepository *gorm.DB + ReleaseRepository *gorm.DB } func InitDependencies() *Dependencies { @@ -53,6 +54,7 @@ func initServices() *Service { func initRepositories(dbClient *gorm.DB) *Repositories { return &Repositories{ ProjectRepository: database.InitProjectRepository(dbClient), + ReleaseRepository: database.InitReleaseRepository(dbClient), } } diff --git a/models/db/Release.go b/models/db/Release.go deleted file mode 100644 index e4d0c26..0000000 --- a/models/db/Release.go +++ /dev/null @@ -1,16 +0,0 @@ -package db - -import ( - "github.com/google/uuid" - "gorm.io/gorm" -) - -type Release struct { - gorm.Model - ReleaseId uuid.UUID `gorm:"primaryKey"` - ProjectReferenceId string - ReleaseVersion string `gorm:"unique"` - SourceMapUrl string // TODO: Check id required - ProjectID string - Project Project `gorm:"foreignKey:ProjectID"` -} diff --git a/models/db/release.go b/models/db/release.go new file mode 100644 index 0000000..3746059 --- /dev/null +++ b/models/db/release.go @@ -0,0 +1,14 @@ +package db + +import ( + "github.com/google/uuid" + "gorm.io/gorm" +) + +type Release struct { + gorm.Model + ReleaseId uuid.UUID `gorm:"primaryKey"` + ReleaseVersion string `gorm:"unique"` + ProjectReferenceId string + Project Project `gorm:"foreignKey:ProjectReferenceId;references:ProjectReferenceId;"` +} From 16b42f1272fd74486c363a485dc85ac9bc770305 Mon Sep 17 00:00:00 2001 From: Lokesh Dugar Date: Sat, 27 Jul 2024 19:54:12 +0530 Subject: [PATCH 6/6] TP-55555 | Exception handler to push errors to kafka --- configs/config.go | 6 ++++ internal/dependencies/dependencies.go | 41 +++++++++++++-------- internal/transport/handler/exception.go | 20 +++++++++++ internal/transport/router/exception.go | 15 ++++++++ internal/transport/server.go | 1 + service/ExceptionService.go | 47 +++++++++++++++++++++++++ service/ReleaseService.go | 11 +++--- 7 files changed, 122 insertions(+), 19 deletions(-) create mode 100644 internal/transport/handler/exception.go create mode 100644 internal/transport/router/exception.go create mode 100644 service/ExceptionService.go diff --git a/configs/config.go b/configs/config.go index 338c4ac..21b7e60 100644 --- a/configs/config.go +++ b/configs/config.go @@ -18,6 +18,7 @@ type AppConfig struct { timezone string httpConfig *HttpConfig clientConfigs *ClientConfigs + kafkaConfig *KafkaConfig } type MigConfig struct { @@ -41,6 +42,7 @@ func LoadConfig() { timezone: getString("timezone", true), clientConfigs: loadClientConfigs(), httpConfig: NewHttpConfig(), + kafkaConfig: NewKafkaConfig(), } } @@ -94,3 +96,7 @@ func readConfig() { func GetHttpConfig() *HttpConfig { return appConfig.httpConfig } + +func GetKafkaConfig() *KafkaConfig { + return appConfig.kafkaConfig +} diff --git a/internal/dependencies/dependencies.go b/internal/dependencies/dependencies.go index 494fe65..f17ea1e 100644 --- a/internal/dependencies/dependencies.go +++ b/internal/dependencies/dependencies.go @@ -7,6 +7,7 @@ import ( "cybertron/internal/transport/handler" "cybertron/pkg/db" httpclient "cybertron/pkg/httpClient" + "cybertron/pkg/kafka/producer" "cybertron/pkg/log" "cybertron/service" "go.uber.org/zap" @@ -22,15 +23,17 @@ type Dependencies struct { } type Service struct { - DocumentService *document.HttpClient - ProjectService *service.ProjectCreator - ReleaseService *service.ReleaseService + DocumentService *document.HttpClient + ProjectService *service.ProjectCreator + ReleaseService *service.ReleaseService + ExceptionService *service.ExceptionService // Add your service here } type Handler struct { - ProjectHandler *handler.ProjectHandler - ReleaseHandler *handler.ReleasesHandler + ProjectHandler *handler.ProjectHandler + ReleaseHandler *handler.ReleasesHandler + ExceptionHandler *handler.ExceptionHandler } type Repositories struct { @@ -43,12 +46,14 @@ func InitDependencies() *Dependencies { repositories := initRepositories(dbClient) logger := log.Log httpClient := httpclient.NewHttpClient(*configs.GetHttpConfig()) + kafkaProducer := initKafkaProducer() documentServiceClient := document.NewDocumentServiceHttpClient(httpClient, logger, configs.GetDocumentServiceHttpClientConfigs()) projectServiceClient := service.NewProjectCreator(logger, dbClient) releaseServiceClient := service.NewReleaseService(logger, dbClient) + exceptionServiceClient := service.NewExceptionService(logger, dbClient, kafkaProducer) - services := initServices(documentServiceClient, projectServiceClient, releaseServiceClient) - handlers := initHandlers(projectServiceClient, releaseServiceClient) + services := initServices(documentServiceClient, projectServiceClient, releaseServiceClient, exceptionServiceClient) + handlers := initHandlers(projectServiceClient, releaseServiceClient, exceptionServiceClient) return &Dependencies{ Service: services, @@ -59,11 +64,12 @@ func InitDependencies() *Dependencies { } } -func initServices(documentService *document.HttpClient, projectService *service.ProjectCreator, releaseService *service.ReleaseService) *Service { +func initServices(documentService *document.HttpClient, projectService *service.ProjectCreator, releaseService *service.ReleaseService, exceptionService *service.ExceptionService) *Service { return &Service{ - DocumentService: documentService, - ProjectService: projectService, - ReleaseService: releaseService, + DocumentService: documentService, + ProjectService: projectService, + ReleaseService: releaseService, + ExceptionService: exceptionService, } } @@ -74,11 +80,18 @@ func initRepositories(dbClient *gorm.DB) *Repositories { } } -func initHandlers(projectService *service.ProjectCreator, releaseService *service.ReleaseService) *Handler { +func initHandlers(projectService *service.ProjectCreator, releaseService *service.ReleaseService, exceotionService *service.ExceptionService) *Handler { projectHandler := handler.NewProjectHandler(projectService) releaseHandler := handler.NewReleaseHandler(releaseService) + exceptionHandler := handler.NewExceptionHandler(exceotionService) return &Handler{ - ProjectHandler: projectHandler, - ReleaseHandler: releaseHandler, + ProjectHandler: projectHandler, + ReleaseHandler: releaseHandler, + ExceptionHandler: exceptionHandler, } } + +func initKafkaProducer() producer.KProducer { + kafkaProducer := producer.NewKProducer(configs.GetEnv(), configs.GetKafkaConfig()) + return kafkaProducer +} diff --git a/internal/transport/handler/exception.go b/internal/transport/handler/exception.go new file mode 100644 index 0000000..c89c029 --- /dev/null +++ b/internal/transport/handler/exception.go @@ -0,0 +1,20 @@ +package handler + +import ( + "cybertron/service" + "github.com/gin-gonic/gin" +) + +type ExceptionHandler struct { + exceptionService *service.ExceptionService +} + +func (h *ExceptionHandler) CatchErrors(c *gin.Context) { + h.exceptionService.CatchErrors(c) +} + +func NewExceptionHandler(es *service.ExceptionService) *ExceptionHandler { + return &ExceptionHandler{ + exceptionService: es, + } +} diff --git a/internal/transport/router/exception.go b/internal/transport/router/exception.go new file mode 100644 index 0000000..e12042b --- /dev/null +++ b/internal/transport/router/exception.go @@ -0,0 +1,15 @@ +package router + +import ( + "cybertron/internal/dependencies" + "cybertron/internal/transport/handler" + "github.com/gin-gonic/gin" +) + +func ExceptionRouter(r *gin.Engine, dep *dependencies.Dependencies) { + exceptionHandler := handler.NewExceptionHandler(dep.Service.ExceptionService) + exceptionRouterGroup := r.Group("/api/v1") + { + exceptionRouterGroup.POST("/catch-errors", exceptionHandler.CatchErrors) + } +} diff --git a/internal/transport/server.go b/internal/transport/server.go index b6b9792..d5f3dbb 100644 --- a/internal/transport/server.go +++ b/internal/transport/server.go @@ -32,6 +32,7 @@ func (s *Server) router() { router.ReadinessRouter(s.gin) router.ProjectRouter(s.gin, s.dependencies) router.ReleasesRouter(s.gin, s.dependencies) + router.ExceptionRouter(s.gin, s.dependencies) } func (s *Server) Start() { diff --git a/service/ExceptionService.go b/service/ExceptionService.go new file mode 100644 index 0000000..5753e53 --- /dev/null +++ b/service/ExceptionService.go @@ -0,0 +1,47 @@ +package service + +import ( + "cybertron/configs" + "cybertron/pkg/encoder" + "cybertron/pkg/kafka/producer" + "cybertron/pkg/log" + "fmt" + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "gorm.io/gorm" + "net/http" +) + +type ExceptionService struct { + logger *log.Logger + dbClient *gorm.DB + kafkaProducer producer.KProducer +} + +func NewExceptionService(logger *log.Logger, dbClient *gorm.DB, kafkaProducer producer.KProducer) *ExceptionService { + return &ExceptionService{ + logger: logger, + dbClient: dbClient, + kafkaProducer: kafkaProducer, + } +} + +func (exceptionService *ExceptionService) CatchErrors(c *gin.Context) { + var errorsPayload []interface{} + + if err := c.BindJSON(&errorsPayload); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid JSON payload"}) + return + } + + headerMap := make(map[string]string) + + for _, errorItem := range errorsPayload { + err := exceptionService.kafkaProducer.PublishEvent(errorItem, configs.GetKafkaConfig().GetTopic("js-error-topic"), uuid.NewString(), headerMap, encoder.JsonEncoderInstance) + if err != nil { + fmt.Println("Failed to push error to kafka") + } + } + + c.JSON(http.StatusOK, gin.H{"status": "success"}) +} diff --git a/service/ReleaseService.go b/service/ReleaseService.go index e5384e1..de63137 100644 --- a/service/ReleaseService.go +++ b/service/ReleaseService.go @@ -27,7 +27,8 @@ func NewReleaseService(logger *log.Logger, dbClient *gorm.DB) *ReleaseService { } } -func (rs *ReleaseService) AddRelease(c *gin.Context) { +// FIXME: This may not be requried now, can be used in source maps services only +func (releaseService *ReleaseService) AddRelease(c *gin.Context) { var releaseBody ReleaseBody if err := c.BindJSON(&releaseBody); err != nil { c.JSON(http.StatusBadRequest, gin.H{ @@ -43,7 +44,7 @@ func (rs *ReleaseService) AddRelease(c *gin.Context) { SourceMapUrl: releaseBody.SourceMapUrl, } - if result := rs.dbClient.Create(&releaseToBeAdded); result.Error != nil { + if result := releaseService.dbClient.Create(&releaseToBeAdded); result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) return } @@ -53,13 +54,13 @@ func (rs *ReleaseService) AddRelease(c *gin.Context) { }) } -func (rs *ReleaseService) GetReleases(c *gin.Context) { +func (releaseService *ReleaseService) GetReleases(c *gin.Context) { projectRefId := c.Query("project_reference_id") var releases []db.Release - rs.dbClient.Where("project_reference_id = ?", projectRefId).Find(&releases) + releaseService.dbClient.Where("project_reference_id = ?", projectRefId).Find(&releases) - if result := rs.dbClient.Find(&releases); result.Error != nil { + if result := releaseService.dbClient.Find(&releases); result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) return }