Skip to content

Commit

Permalink
code review and refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
ardan-bkennedy committed Jan 23, 2024
1 parent 3c31bca commit d75310b
Show file tree
Hide file tree
Showing 86 changed files with 11,491 additions and 823 deletions.
Binary file modified app/services/.DS_Store
Binary file not shown.
6 changes: 3 additions & 3 deletions business/data/dbtest/dbtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func StartDB() (*docker.Container, error) {

fmt.Printf("Image: %s\n", image)
fmt.Printf("ContainerID: %s\n", c.ID)
fmt.Printf("Host: %s\n", c.Host)
fmt.Printf("HostPort: %s\n", c.HostPort)

return c, nil
}
Expand Down Expand Up @@ -65,7 +65,7 @@ func NewTest(t *testing.T, c *docker.Container, name string) *Test {
dbM, err := sqldb.Open(sqldb.Config{
User: "postgres",
Password: "postgres",
Host: c.Host,
HostPort: c.HostPort,
Name: "postgres",
DisableTLS: true,
})
Expand Down Expand Up @@ -94,7 +94,7 @@ func NewTest(t *testing.T, c *docker.Container, name string) *Test {
db, err := sqldb.Open(sqldb.Config{
User: "postgres",
Password: "postgres",
Host: c.Host,
HostPort: c.HostPort,
Name: dbName,
DisableTLS: true,
})
Expand Down
59 changes: 13 additions & 46 deletions business/data/migrate/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,43 @@ package migrate
import (
"context"
"database/sql"
_ "embed" // Calls init function.
_ "embed"
"errors"
"fmt"

"github.com/ardanlabs/darwin/v2"
"github.com/ardanlabs/liarsdice/business/data/sqldb"
"github.com/ardanlabs/darwin/v3"
"github.com/ardanlabs/darwin/v3/dialects/postgres"
"github.com/ardanlabs/darwin/v3/drivers/generic"
"github.com/ardanlabs/service/business/data/sqldb"
"github.com/jmoiron/sqlx"
)

var (
//go:embed sql/schema.sql
schemaDoc string
//go:embed sql/migrate.sql
migrateDoc string

//go:embed sql/seed.sql
seedDoc string

//go:embed sql/delete.sql
deleteDoc string
)

// Migrate attempts to bring the schema for db up to date with the migrations
// Migrate attempts to bring the database up to date with the migrations
// defined in this package.
func Migrate(ctx context.Context, db *sqlx.DB) error {
if err := sqldb.StatusCheck(ctx, db); err != nil {
return fmt.Errorf("status check database: %w", err)
}

driver, err := darwin.NewGenericDriver(db.DB, darwin.PostgresDialect{})
driver, err := generic.New(db.DB, postgres.Dialect{})
if err != nil {
return fmt.Errorf("construct darwin driver: %w", err)
}

d := darwin.New(driver, darwin.ParseMigrations(schemaDoc))
d := darwin.New(driver, darwin.ParseMigrations(migrateDoc))
return d.Migrate()
}

// Seed runs the set of seed-data queries against db. The queries are ran in a
// transaction and rolled back if any fail.
// Seed runs the seed document defined in this package against db. The queries
// are run in a transaction and rolled back if any fail.
func Seed(ctx context.Context, db *sqlx.DB) (err error) {
if err := sqldb.StatusCheck(ctx, db); err != nil {
return fmt.Errorf("status check database: %w", err)
Expand All @@ -57,45 +56,13 @@ func Seed(ctx context.Context, db *sqlx.DB) (err error) {
if errors.Is(errTx, sql.ErrTxDone) {
return
}
err = fmt.Errorf("rollback: %w", errTx)
return
}
}()

if _, err := tx.Exec(seedDoc); err != nil {
return fmt.Errorf("exec: %w", err)
}

if err := tx.Commit(); err != nil {
return fmt.Errorf("commit: %w", err)
}

return nil
}

// DeleteAll runs the set of Drop-table queries against db. The queries are ran in a
// transaction and rolled back if any fail.
func DeleteAll(ctx context.Context, db *sqlx.DB) error {
if err := sqldb.StatusCheck(ctx, db); err != nil {
return fmt.Errorf("status check database: %w", err)
}

tx, err := db.Begin()
if err != nil {
return err
}

defer func() {
if errTx := tx.Rollback(); errTx != nil {
if errors.Is(errTx, sql.ErrTxDone) {
return
}
err = fmt.Errorf("rollback: %w", errTx)
return
}
}()

if _, err := tx.Exec(deleteDoc); err != nil {
if _, err := tx.Exec(seedDoc); err != nil {
return fmt.Errorf("exec: %w", err)
}

Expand Down
3 changes: 0 additions & 3 deletions business/data/migrate/sql/delete.sql

This file was deleted.

File renamed without changes.
4 changes: 2 additions & 2 deletions business/data/sqldb/sqldb.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var (
type Config struct {
User string
Password string
Host string
HostPort string
Name string
Schema string
MaxIdleConns int
Expand All @@ -59,7 +59,7 @@ func Open(cfg Config) (*sqlx.DB, error) {
u := url.URL{
Scheme: "postgres",
User: url.UserPassword(cfg.User, cfg.Password),
Host: cfg.Host,
Host: cfg.HostPort,
Path: cfg.Name,
RawQuery: q.Encode(),
}
Expand Down
2 changes: 1 addition & 1 deletion business/web/v1/mid/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

// Authenticate validates a JWT from the `Authorization` header.
func Authenticate(a *auth.Auth) web.Middleware {
func Authenticate(a *auth.Auth) web.MidHandler {
m := func(handler web.Handler) web.Handler {
h := func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
claims, err := a.Authenticate(ctx, r.Header.Get("authorization"))
Expand Down
3 changes: 2 additions & 1 deletion business/web/v1/mid/cors.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ import (
)

// Cors sets the response headers needed for Cross-Origin Resource Sharing
func Cors(origins []string) web.Middleware {
func Cors(origins []string) web.MidHandler {
m := func(handler web.Handler) web.Handler {
h := func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
for _, origin := range origins {
w.Header().Set("Access-Control-Allow-Origin", origin)
}

w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
w.Header().Set("Access-Control-Max-Age", "86400")
Expand Down
2 changes: 0 additions & 2 deletions business/web/v1/mid/doc.go

This file was deleted.

2 changes: 1 addition & 1 deletion business/web/v1/mid/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
// Errors handles errors coming out of the call chain. It detects normal
// application errors which are used to respond to the client in a uniform way.
// Unexpected errors (status >= 500) are logged.
func Errors(log *logger.Logger) web.Middleware {
func Errors(log *logger.Logger) web.MidHandler {
m := func(handler web.Handler) web.Handler {
h := func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
if err := handler(ctx, w, r); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion business/web/v1/mid/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

// Logger writes some information about the request to the logs in the
// format: TraceID : (200) GET /foo -> IP ADDR (latency)
func Logger(log *logger.Logger) web.Middleware {
func Logger(log *logger.Logger) web.MidHandler {
m := func(handler web.Handler) web.Handler {
h := func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
v := web.GetValues(ctx)
Expand Down
9 changes: 6 additions & 3 deletions business/web/v1/mid/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ import (
)

// Metrics updates program counters.
func Metrics() web.Middleware {
func Metrics() web.MidHandler {
m := func(handler web.Handler) web.Handler {
h := func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
ctx = metrics.Set(ctx)

err := handler(ctx, w, r)

metrics.AddRequests(ctx)
metrics.AddGoroutines(ctx)
n := metrics.AddRequests(ctx)

if n%1000 == 0 {
metrics.AddGoroutines(ctx)
}

if err != nil {
metrics.AddErrors(ctx)
Expand Down
2 changes: 1 addition & 1 deletion business/web/v1/mid/panics.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (

// Panics recovers from panics and converts the panic to an error so it is
// reported in Metrics and handled in Errors.
func Panics() web.Middleware {
func Panics() web.MidHandler {
m := func(handler web.Handler) web.Handler {
h := func(ctx context.Context, w http.ResponseWriter, r *http.Request) (err error) {

Expand Down
13 changes: 7 additions & 6 deletions foundation/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (

// Container tracks information about the docker container started for tests.
type Container struct {
ID string
Host string // IP:Port
ID string
HostPort string
}

// StartContainer starts the specified container for running tests.
Expand All @@ -24,8 +24,8 @@ func StartContainer(image string, port string, dockerArgs []string, appArgs []st
arg = append(arg, image)
arg = append(arg, appArgs...)

cmd := exec.Command("docker", arg...)
var out bytes.Buffer
cmd := exec.Command("docker", arg...)
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("could not start container %s: %w", image, err)
Expand All @@ -39,8 +39,8 @@ func StartContainer(image string, port string, dockerArgs []string, appArgs []st
}

c := Container{
ID: id,
Host: net.JoinHostPort(hostIP, hostPort),
ID: id,
HostPort: net.JoinHostPort(hostIP, hostPort),
}

return &c, nil
Expand All @@ -65,14 +65,15 @@ func DumpContainerLogs(id string) []byte {
if err != nil {
return nil
}

return out
}

func extractIPPort(id string, port string) (hostIP string, hostPort string, err error) {
tmpl := fmt.Sprintf("[{{range $k,$v := (index .NetworkSettings.Ports \"%s/tcp\")}}{{json $v}}{{end}}]", port)

cmd := exec.Command("docker", "inspect", "-f", tmpl, id)
var out bytes.Buffer
cmd := exec.Command("docker", "inspect", "-f", tmpl, id)
cmd.Stdout = &out
if err := cmd.Run(); err != nil {
return "", "", fmt.Errorf("could not inspect container %s: %w", id, err)
Expand Down
26 changes: 13 additions & 13 deletions foundation/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ import (
"log/slog"
)

// TraceIDFunc represents a function that can return the trace id from
// TraceIDFn represents a function that can return the trace id from
// the specified context.
type TraceIDFunc func(ctx context.Context) string
type TraceIDFn func(ctx context.Context) string

// Logger represents a logger for logging information.
type Logger struct {
handler slog.Handler
traceIDFunc TraceIDFunc
handler slog.Handler
traceIDFn TraceIDFn
}

// New constructs a new log for application use.
func New(w io.Writer, minLevel Level, serviceName string, traceIDFunc TraceIDFunc) *Logger {
return new(w, minLevel, serviceName, traceIDFunc, Events{})
func New(w io.Writer, minLevel Level, serviceName string, traceIDFn TraceIDFn) *Logger {
return new(w, minLevel, serviceName, traceIDFn, Events{})
}

// NewWithEvents constructs a new log for application use with events.
func NewWithEvents(w io.Writer, minLevel Level, serviceName string, traceIDFunc TraceIDFunc, events Events) *Logger {
return new(w, minLevel, serviceName, traceIDFunc, events)
func NewWithEvents(w io.Writer, minLevel Level, serviceName string, traceIDFn TraceIDFn, events Events) *Logger {
return new(w, minLevel, serviceName, traceIDFn, events)
}

// NewWithHandler returns a new log for application use with the underlying
Expand Down Expand Up @@ -96,15 +96,15 @@ func (log *Logger) write(ctx context.Context, level Level, caller int, msg strin

r := slog.NewRecord(time.Now(), slogLevel, msg, pcs[0])

if log.traceIDFunc != nil {
args = append(args, "trace_id", log.traceIDFunc(ctx))
if log.traceIDFn != nil {
args = append(args, "trace_id", log.traceIDFn(ctx))
}
r.Add(args...)

log.handler.Handle(ctx, r)
}

func new(w io.Writer, minLevel Level, serviceName string, traceIDFunc TraceIDFunc, events Events) *Logger {
func new(w io.Writer, minLevel Level, serviceName string, traceIDFn TraceIDFn, events Events) *Logger {

// Convert the file name to just the name.ext when this key/value will
// be logged.
Expand Down Expand Up @@ -137,7 +137,7 @@ func new(w io.Writer, minLevel Level, serviceName string, traceIDFunc TraceIDFun
handler = handler.WithAttrs(attrs)

return &Logger{
handler: handler,
traceIDFunc: traceIDFunc,
handler: handler,
traceIDFn: traceIDFn,
}
}
12 changes: 6 additions & 6 deletions foundation/logger/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ func toRecord(r slog.Record) Record {
}
}

// EventFunc is a function to be executed when configured against a log level.
type EventFunc func(ctx context.Context, r Record)
// EventFn is a function to be executed when configured against a log level.
type EventFn func(ctx context.Context, r Record)

// Events contains an assignment of an event function to a log level.
type Events struct {
Debug EventFunc
Info EventFunc
Warn EventFunc
Error EventFunc
Debug EventFn
Info EventFn
Warn EventFn
Error EventFn
}
7 changes: 2 additions & 5 deletions foundation/validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,17 @@ func init() {
// Check validates the provided model against it's declared tags.
func Check(val any) error {
if err := validate.Struct(val); err != nil {

// Use a type assertion to get the real error value.
verrors, ok := err.(validator.ValidationErrors)
if !ok {
return err
}

var fields FieldErrors
for _, verror := range verrors {
field := FieldError{
fields = append(fields, FieldError{
Field: verror.Field(),
Err: verror.Translate(translator),
}
fields = append(fields, field)
})
}

return fields
Expand Down
Loading

0 comments on commit d75310b

Please sign in to comment.