Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: major refactor which introduces new practices #5

Merged
merged 26 commits into from
Apr 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.18
go-version: 1.22
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ on:
- master
jobs:
test:
name: "Test with Go 1.19"
name: "Test with Go 1.22"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up Go 1.19
- name: Set up Go 1.22
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.22

- name: Test
run: go test -coverprofile=coverage.txt -covermode=atomic $(go list ./... | grep -v /cmd)
257 changes: 108 additions & 149 deletions README.md

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions cmd/server/grpc/grpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package grpc

import "github.com/bnkamalesh/goapp/internal/api"

type GRPC struct {
apis api.Server
}

func New(apis api.Server) *GRPC {
return &GRPC{
apis: apis,
}
}
14 changes: 8 additions & 6 deletions internal/server/http/handlers.go → cmd/server/http/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import (
"runtime/debug"

"github.com/bnkamalesh/errors"
"github.com/bnkamalesh/webgo/v6"
"github.com/bnkamalesh/webgo/v7"

"github.com/bnkamalesh/goapp/internal/api"
"github.com/bnkamalesh/goapp/internal/pkg/logger"
)

// Handlers struct has all the dependencies required for HTTP handlers
type Handlers struct {
api *api.API
apis api.Server
home *template.Template
}

Expand Down Expand Up @@ -56,7 +56,7 @@ func (h *Handlers) routes() []*webgo.Route {
// Health is the HTTP handler to return the status of the app including the version, and other details
// This handler uses webgo to respond to the http request
func (h *Handlers) Health(w http.ResponseWriter, r *http.Request) error {
out, err := h.api.Health()
out, err := h.apis.ServerHealth()
if err != nil {
return err
}
Expand All @@ -80,7 +80,7 @@ func (h *Handlers) HelloWorld(w http.ResponseWriter, r *http.Request) error {
struct {
Message string
}{
Message: "welcome to the home page!",
Message: "Welcome to the Home Page!",
},
)
if err != nil {
Expand All @@ -106,7 +106,9 @@ func errWrapper(h func(w http.ResponseWriter, r *http.Request) error) http.Handl

status, msg, _ := errors.HTTPStatusCodeMessage(err)
webgo.SendError(w, msg, status)
_ = logger.Error(errors.Stacktrace(err))
if status > 499 {
logger.Error(r.Context(), errors.Stacktrace(err))
}
}
}

Expand All @@ -118,7 +120,7 @@ func panicRecoverer(w http.ResponseWriter, r *http.Request, next http.HandlerFun
}
webgo.R500(w, errors.DefaultMessage)

_ = logger.Error(fmt.Sprintf("%+v", p))
logger.Error(r.Context(), fmt.Sprintf("%+v", p))
fmt.Println(string(debug.Stack()))
}()

Expand Down
27 changes: 27 additions & 0 deletions cmd/server/http/handlers_usernotes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package http

import (
"encoding/json"
"net/http"

"github.com/bnkamalesh/errors"
"github.com/bnkamalesh/goapp/internal/usernotes"
"github.com/bnkamalesh/webgo/v7"
)

func (h *Handlers) CreateUserNote(w http.ResponseWriter, r *http.Request) error {
unote := new(usernotes.Note)
err := json.NewDecoder(r.Body).Decode(unote)
if err != nil {
return errors.InputBodyErr(err, "invalid JSON provided")
}

un, err := h.apis.CreateUserNote(r.Context(), unote)
if err != nil {
return err
}

webgo.R200(w, un)

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"net/http"

"github.com/bnkamalesh/errors"
"github.com/bnkamalesh/webgo/v6"
"github.com/bnkamalesh/webgo/v7"

"github.com/bnkamalesh/goapp/internal/users"
)
Expand All @@ -19,21 +19,13 @@ func (h *Handlers) CreateUser(w http.ResponseWriter, r *http.Request) error {
return errors.InputBodyErr(err, "invalid JSON provided")
}

createdUser, err := h.api.CreateUser(r.Context(), u)
createdUser, err := h.apis.CreateUser(r.Context(), u)
if err != nil {
return err
}

b, err := json.Marshal(createdUser)
if err != nil {
return errors.InputBodyErr(err, "invalid input body provided")
}
webgo.R200(w, createdUser)

w.Header().Set("Content-Type", "application/json")
_, err = w.Write(b)
if err != nil {
return errors.Wrap(err, "failed to respond")
}
return nil
}

Expand All @@ -42,11 +34,12 @@ func (h *Handlers) ReadUserByEmail(w http.ResponseWriter, r *http.Request) error
wctx := webgo.Context(r)
email := wctx.Params()["email"]

out, err := h.api.ReadUserByEmail(r.Context(), email)
out, err := h.apis.ReadUserByEmail(r.Context(), email)
if err != nil {
return err
}

webgo.R200(w, out)

return nil
}
106 changes: 106 additions & 0 deletions cmd/server/http/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package http

import (
"context"
"fmt"
"net/http"
"strconv"
"strings"
"time"

"github.com/bnkamalesh/errors"
"github.com/bnkamalesh/goapp/internal/api"
"github.com/bnkamalesh/goapp/internal/pkg/apm"
"github.com/bnkamalesh/webgo/v7"
"github.com/bnkamalesh/webgo/v7/middleware/accesslog"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)

// Config holds all the configuration required to start the HTTP server
type Config struct {
Host string
Port uint16

ReadTimeout time.Duration
WriteTimeout time.Duration
DialTimeout time.Duration

TemplatesBasePath string
EnableAccessLog bool
}

type HTTP struct {
listener string
server *webgo.Router
}

// Start starts the HTTP server
func (h *HTTP) Start() error {
h.server.Start()
return nil
}

func (h *HTTP) Shutdown(ctx context.Context) error {
err := h.server.Shutdown()
if err != nil {
return errors.Wrap(err, "failed shutting down HTTP server")
}

return nil
}

// NewService returns an instance of HTTP with all its dependencies set
func NewService(cfg *Config, apis api.Server) (*HTTP, error) {
home, err := loadHomeTemplate(cfg.TemplatesBasePath)
if err != nil {
return nil, err
}

handlers := &Handlers{
apis: apis,
home: home,
}

router := webgo.NewRouter(
&webgo.Config{
Host: cfg.Host,
Port: strconv.Itoa(int(cfg.Port)),
ReadTimeout: cfg.ReadTimeout,
WriteTimeout: cfg.WriteTimeout,
ShutdownTimeout: cfg.WriteTimeout * 2,
},
handlers.routes()...,
)

if cfg.EnableAccessLog {
router.Use(accesslog.AccessLog)
router.UseOnSpecialHandlers(accesslog.AccessLog)
}
router.Use(panicRecoverer)

otelopts := []otelhttp.Option{
// in this app, /-/ prefixed routes are used for healthchecks, readiness checks etc.
otelhttp.WithFilter(func(req *http.Request) bool {
return !strings.HasPrefix(req.URL.Path, "/-/")
}),
// the span name formatter is used to reduce the cardinality of metrics generated
// when using URIs with variables in it
otelhttp.WithSpanNameFormatter(func(operation string, r *http.Request) string {
wctx := webgo.Context(r)
if wctx == nil {
return r.URL.Path
}
return wctx.Route.Pattern
}),
}

apmMw := apm.NewHTTPMiddleware(otelopts...)
router.Use(func(w http.ResponseWriter, r *http.Request, hf http.HandlerFunc) {
apmMw(hf).ServeHTTP(w, r)
})

return &HTTP{
server: router,
listener: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
}, nil
}
41 changes: 41 additions & 0 deletions cmd/server/http/web/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Hello world</title>
<style>
html,
body {
font-size: 16px;
line-height: 1.5em;
min-width: 100vw;
min-height: 100vh;
}
body {
font-family: sans-serif;
background-color: #efefef;
color: #222;
height: 100vh;
width: 100vw;
overflow: hidden;
}
main {
margin: 40vh auto 0;
width: 35rem;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: "Roboto", sans-serif;
font-weight: 400;
}
</style>
</head>
<body>
<main>
<h3 id="colorize" style="text-align: center">{{.Message}}</h3>
</main>
</body>
</html>
14 changes: 14 additions & 0 deletions cmd/subscribers/kafka/kafka.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Package kafka implements the Kafka subscription functionality
package kafka

import "github.com/bnkamalesh/goapp/internal/api"

type Kafka struct {
apis api.Subscriber
}

func New(apis api.Subscriber) *Kafka {
return &Kafka{
apis: apis,
}
}
10 changes: 5 additions & 5 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.20 AS builder
FROM golang:1.22 AS builder

COPY ../ /app
WORKDIR /app
Expand All @@ -13,10 +13,10 @@ LABEL MAINTAINER Author <[email protected]>

# Following commands are for installing CA certs (for proper functioning of HTTPS and other TLS)
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
netbase \
&& rm -rf /var/lib/apt/lists/ \
&& apt-get autoremove -y && apt-get autoclean -y
ca-certificates \
netbase \
&& rm -rf /var/lib/apt/lists/ \
&& apt-get autoremove -y && apt-get autoclean -y

# Add new user 'appuser'. App should be run without root privileges as a security measure
RUN adduser --home "/appuser" --disabled-password appuser \
Expand Down
17 changes: 13 additions & 4 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
version: "3.9"
services:
redis:
image: "redis:alpine"
image: "redis:7"
networks:
- goapp_network

postgres:
image: "postgres"
image: "postgres:16"
environment:
POSTGRES_PASSWORD: gauserpassword
POSTGRES_USER: gauser
POSTGRES_DB: goapp
ports:
- "5432:5432"
networks:
- goapp_network

goapp:
image: golang:1.20
image: golang:1.22
volumes:
- ${PWD}:/app
working_dir: /app
# command: go run main.go
tty: true
environment:
TEMPLATES_BASEPATH: /app/cmd/server/http/web/templates
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
POSTGRES_STORENAME: "goapp"
POSTGRES_USERNAME: "gauser"
POSTGRES_PASSWORD: "gauserpassword"
command: go run main.go
ports:
- "8080:8080"
depends_on:
Expand Down
Loading
Loading