Skip to content

Commit

Permalink
1. Moved resources out of cmd to its own internal folder
Browse files Browse the repository at this point in the history
2. Template updates with abstractions over common handlers and service handler
3. Ping demo handler baked in with the generated service
4. Health endpoint auto caller for service(s) Health check
  • Loading branch information
PereRohit authored Sep 11, 2022
1 parent 73f73a9 commit 55f5b2e
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 65 deletions.
4 changes: 3 additions & 1 deletion cmd/gosvc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import (
"strings"
"text/template"

"github.com/PereRohit/gosvc/internal"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)

var (
//go:embed resources/*
f embed.FS

re = regexp.MustCompile(`[^\w]`)
Expand Down Expand Up @@ -144,6 +144,8 @@ func CommandRunner(command string, args ...string) {
func main() {
flag.Parse()

f = internal.GetEmbeddedFS()

initModule := strings.TrimSpace(*moduleName)
if len(initModule) <= 0 {
fmt.Fprintf(os.Stderr, "error: invalid usage\n")
Expand Down
37 changes: 0 additions & 37 deletions cmd/gosvc/resources/internal/handler/handler.go.tmpl

This file was deleted.

27 changes: 0 additions & 27 deletions cmd/gosvc/resources/internal/router/router.go.tmpl

This file was deleted.

12 changes: 12 additions & 0 deletions internal/resources.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package internal

import "embed"

var (
//go:embed resources
f embed.FS
)

func GetEmbeddedFS() embed.FS {
return f
}
3 changes: 3 additions & 0 deletions internal/resources/README.md.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# {{.Service}}

##### Generated with [gosvc cli](https://github.com/PereRohit/gosvc)
File renamed without changes.
File renamed without changes.
67 changes: 67 additions & 0 deletions internal/resources/internal/handler/common.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package handler

import (
"net/http"
"sync"

"github.com/PereRohit/util/response"
)

//go:generate mockgen --build_flags=--mod=mod --destination=./../../pkg/mock/mock_common.go --package=mock {{.Module}}/internal/handler Commoner,HealthChecker

type Commoner interface {
MethodNotAllowed(http.ResponseWriter, *http.Request)
RouteNotFound(http.ResponseWriter, *http.Request)
HealthCheck(http.ResponseWriter, *http.Request)
}

type HealthChecker interface {
HealthCheck() (svcName string, msg string, stat bool)
}

type common struct {
sync.Mutex
services []HealthChecker
}

var c = common{}

func AddHealthChecker(h HealthChecker) {
c.Lock()
defer c.Unlock()
c.services = append(c.services, h)
}

func NewCommonSvc() Commoner {
return &c
}

func (common) MethodNotAllowed(w http.ResponseWriter, _ *http.Request) {
response.ToJson(w, http.StatusMethodNotAllowed, http.StatusText(http.StatusMethodNotAllowed), nil)
}

func (common) RouteNotFound(w http.ResponseWriter, _ *http.Request) {
response.ToJson(w, http.StatusNotFound, http.StatusText(http.StatusNotFound), nil)
}

func (common) HealthCheck(w http.ResponseWriter, _ *http.Request) {
type svcHealthStat struct {
Status string `json:"status"`
Message string `json:"message,omitempty"`
}

svcUpdate := map[string]svcHealthStat{}

for _, svc := range c.services {
name, msg, ok := svc.HealthCheck()
stat := http.StatusText(http.StatusOK)
if !ok {
stat = "Not " + stat
}
svcUpdate[name] = svcHealthStat{
Status: stat,
Message: msg,
}
}
response.ToJson(w, http.StatusOK, http.StatusText(http.StatusOK), svcUpdate)
}
67 changes: 67 additions & 0 deletions internal/resources/internal/handler/handler.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package handler

import (
"fmt"
"net/http"

"github.com/PereRohit/util/request"
"github.com/PereRohit/util/response"

"{{.Module}}/internal/logic"
"{{.Module}}/internal/model"
)

const {{.Service}}Name = "{{.Service}}"

var (
svc = &{{.Service}}{}
)

//go:generate mockgen --build_flags=--mod=mod --destination=./../../pkg/mock/mock_handler.go --package=mock {{.Module}}/internal/handler {{.Service}}Handler

type {{.Service}}Handler interface {
HealthChecker
Ping(w http.ResponseWriter, r *http.Request)
}

type {{.Service}} struct {
logic logic.{{.Service}}LogicIer
}

func init() {
AddHealthChecker(svc)
}

func New{{.Service}}() {{.Service}}Handler {
svc = &{{.Service}}{
logic: logic.New{{.Service}}Logic(),
}

return svc
}

func (svc {{.Service}}) HealthCheck() (svcName string, msg string, stat bool) {
set := false
defer func() {
svcName = {{.Service}}Name
if !set {
msg = ""
stat = true
}
}()
return
}

func (svc {{.Service}}) Ping(w http.ResponseWriter, r *http.Request) {
req := &model.PingRequest{}

suggestedCode, err := request.FromJson(r, req)
if err != nil {
response.ToJson(w, suggestedCode, fmt.Sprintf("FAILED: %s", err.Error()), nil)
return
}
// call logic
resp := svc.logic.Ping(req)
response.ToJson(w, resp.Status, resp.Message, resp.Data)
return
}
26 changes: 26 additions & 0 deletions internal/resources/internal/logic/logic.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package logic

import (
"net/http"

respModel "github.com/PereRohit/util/model"
"{{.Module}}/internal/model"
)

type {{.Service}}LogicIer interface {
Ping(*model.PingRequest) *respModel.Response
}

type {{.Service}}Logic struct{}

func New{{.Service}}Logic() {{.Service}}LogicIer {
return &{{.Service}}Logic{}
}

func (l {{.Service}}Logic) Ping(req *model.PingRequest) *respModel.Response {
return &respModel.Response{
Status: http.StatusOK,
Message: "Pong",
Data: req.Data,
}
}
4 changes: 4 additions & 0 deletions internal/resources/internal/logic/mockgen.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package logic

//go:generate mockgen --build_flags=--mod=mod --destination=./../../pkg/mock/mock_logic.go --package=mock {{.Module}}/internal/logic {{.Service}}LogicIer

5 changes: 5 additions & 0 deletions internal/resources/internal/model/model.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package model

type PingRequest struct {
Data any `json:"data" validate:"required"`
}
37 changes: 37 additions & 0 deletions internal/resources/internal/router/router.go.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package router

import (
"net/http"

"github.com/PereRohit/util/constant"
"github.com/PereRohit/util/middleware"
"github.com/gorilla/mux"

"{{.Module}}/internal/handler"
)

func Register() *mux.Router {
m := mux.NewRouter()

m.StrictSlash(true)
m.Use(middleware.RequestHijacker)
m.Use(middleware.RecoverPanic)

commons := handler.NewCommonSvc()
m.HandleFunc(constant.HealthRoute, commons.HealthCheck).Methods(http.MethodGet)
m.NotFoundHandler = http.HandlerFunc(commons.RouteNotFound)
m.MethodNotAllowedHandler = http.HandlerFunc(commons.MethodNotAllowed)

// attach routes for services below
m = attach{{.Service}}Routes(m)

return m
}

func attach{{.Service}}Routes(m *mux.Router) *mux.Router {
svc := handler.New{{.Service}}()

m.HandleFunc("/ping", svc.Ping).Methods(http.MethodPost)

return m
}

0 comments on commit 55f5b2e

Please sign in to comment.