Skip to content

Commit

Permalink
chore: sync with go-monolith-example
Browse files Browse the repository at this point in the history
  • Loading branch information
powerman committed May 30, 2021
1 parent dd92f14 commit 7c7c69f
Show file tree
Hide file tree
Showing 43 changed files with 674 additions and 404 deletions.
11 changes: 5 additions & 6 deletions cmd/address-book/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

//nolint:gochecknoglobals // Main.
var (
svc = &service{}
svc = &Service{}

log = structlog.New(structlog.KeyUnit, "main")

Expand All @@ -45,12 +45,13 @@ var (
)

func main() {
_ = os.Unsetenv("GO_TEST_DISABLE_SENSITIVE")
err := def.Init()
if err != nil {
log.Fatalf("failed to get defaults: %s", err)
}

err = initService(rootCmd, serveCmd)
err = svc.Init(rootCmd, serveCmd)
if err != nil {
log.Fatalf("failed to init service: %s", err)
}
Expand All @@ -77,15 +78,13 @@ func runServeWithGracefulShutdown(_ *cobra.Command, _ []string) error {
defer cancel()

ctxShutdown, shutdown := context.WithCancel(context.Background())
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGABRT, syscall.SIGTERM)
go func() { <-sigc; shutdown() }()
ctxShutdown, _ = signal.NotifyContext(ctxShutdown, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGABRT, syscall.SIGTERM)
go func() {
<-ctxShutdown.Done()
time.Sleep(serveShutdownTimeout.Value(nil))
log.PrintErr("failed to graceful shutdown", "version", def.Version())
os.Exit(1)
}()

return svc.runServe(ctxStartup, ctxShutdown, shutdown)
return svc.RunServe(ctxStartup, ctxShutdown, shutdown)
}
18 changes: 9 additions & 9 deletions cmd/address-book/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ type Ctx = context.Context

var reg = prometheus.NewPedanticRegistry() //nolint:gochecknoglobals // Metrics are global anyway.

type service struct {
type Service struct {
cfg *config.ServeConfig
repo *dal.Repo
appl *app.App
srv *restapi.Server
}

func initService(cmd, serveCmd *cobra.Command) error {
func (s *Service) Init(cmd, serveCmd *cobra.Command) error {
namespace := regexp.MustCompile(`[^a-zA-Z0-9]+`).ReplaceAllString(def.ProgName, "_")
initMetrics(reg, namespace)
dal.InitMetrics(reg, namespace)
Expand All @@ -48,7 +48,7 @@ func initService(cmd, serveCmd *cobra.Command) error {
})
}

func (s *service) runServe(ctxStartup, ctxShutdown Ctx, shutdown func()) (err error) {
func (s *Service) RunServe(ctxStartup, ctxShutdown Ctx, shutdown func()) (err error) {
log := structlog.FromContext(ctxShutdown, nil)
if s.cfg == nil {
s.cfg, err = config.GetServe()
Expand All @@ -69,7 +69,7 @@ func (s *service) runServe(ctxStartup, ctxShutdown Ctx, shutdown func()) (err er
}
s.srv, err = openapi.NewServer(s.appl, openapi.Config{
APIKeyAdmin: s.cfg.APIKeyAdmin,
Addr: s.cfg.Addr,
Addr: s.cfg.BindAddr,
})
if err != nil {
return log.Err("failed to openapi.NewServer", "err", err)
Expand All @@ -85,14 +85,14 @@ func (s *service) runServe(ctxStartup, ctxShutdown Ctx, shutdown func()) (err er
return nil
}

func (s *service) connectRepo(ctx Ctx) (interface{}, error) {
return dal.New(ctx, s.cfg.MySQLGooseDir, s.cfg.MySQL)
func (s *Service) connectRepo(ctx Ctx) (interface{}, error) {
return dal.New(ctx, s.cfg.GooseMySQLDir, s.cfg.MySQL)
}

func (s *service) serveMetrics(ctx Ctx) error {
return serve.Metrics(ctx, s.cfg.MetricsAddr, reg)
func (s *Service) serveMetrics(ctx Ctx) error {
return serve.Metrics(ctx, s.cfg.BindMetricsAddr, reg)
}

func (s *service) serveOpenAPI(ctx Ctx) error {
func (s *Service) serveOpenAPI(ctx Ctx) error {
return serve.OpenAPI(ctx, s.srv, "OpenAPI")
}
8 changes: 4 additions & 4 deletions cmd/address-book/service_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
func TestSmoke(tt *testing.T) {
t := check.T(tt)

s := &service{cfg: cfg}
s := &Service{cfg: cfg}

tempDBCfg, cleanup, err := mysqlx.EnsureTempDB(tLogger(*t), "", cfg.MySQL)
cfg.MySQL = tempDBCfg // Assign to cfg and not s.cfg as a reminder: they are the same.
Expand All @@ -32,19 +32,19 @@ func TestSmoke(tt *testing.T) {
defer cancel()
ctxShutdown, shutdown := context.WithCancel(ctx)
errc := make(chan error)
go func() { errc <- s.runServe(ctxStartup, ctxShutdown, shutdown) }()
go func() { errc <- s.RunServe(ctxStartup, ctxShutdown, shutdown) }()
defer func() {
shutdown()
t.Nil(<-errc, "RunServe")
if s.repo != nil {
s.repo.Close()
}
}()
t.Must(t.Nil(netx.WaitTCPPort(ctxStartup, cfg.Addr), "connect to service"))
t.Must(t.Nil(netx.WaitTCPPort(ctxStartup, cfg.BindAddr), "connect to service"))

openapiClient := client.NewHTTPClientWithConfig(nil, &client.TransportConfig{
Schemes: []string{"http"},
Host: cfg.Addr.String(),
Host: cfg.BindAddr.String(),
BasePath: client.DefaultBasePath,
})

Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require (
github.com/golangci/golangci-lint v1.40.1
github.com/jessevdk/go-flags v1.4.0
github.com/jmoiron/sqlx v1.3.4
github.com/lib/pq v1.9.0
github.com/mattn/goveralls v0.0.9
github.com/powerman/appcfg v0.6.0
github.com/powerman/check v1.3.1
Expand All @@ -27,6 +28,7 @@ require (
github.com/powerman/must v0.1.0
github.com/powerman/mysqlx v0.3.3
github.com/powerman/narada4d v1.7.1
github.com/powerman/sensitive v0.0.6
github.com/powerman/sqlxx v0.2.0
github.com/powerman/structlog v0.7.1
github.com/prometheus/client_golang v1.10.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,8 @@ github.com/powerman/mysqlx v0.3.3/go.mod h1:ZSl17PWU2DgwM2KjN8OrdAq9tYC5p4Xm3lTN
github.com/powerman/narada4d v1.7.1 h1:G6hkEQxfCBWIsrUtB4MyWq4c84qcS/3XsBQLWUuUyik=
github.com/powerman/narada4d v1.7.1/go.mod h1:LUOXFkHgtSwPqtrZx+F/Ab1PqOiL96O3GfYnoKfg6T0=
github.com/powerman/pqx v0.6.1/go.mod h1:EJGFN0+vvTWFqwT1bTrnVWrJ8hO7RAW6rp2JVhYwrVE=
github.com/powerman/sensitive v0.0.6 h1:cLE/om0/J2mpiI/Z6o1r9AUbs8Q7G1vhISEbdGeIGQc=
github.com/powerman/sensitive v0.0.6/go.mod h1:BT3bBXUqTDKM13MXlYvN4Csg9WXSZblJ12mGgHAY/wU=
github.com/powerman/sqlxx v0.2.0 h1:NA2Z+o7Q6Lu9UqwGFqqPePKWoPYZ5doOsBnfstCU1uU=
github.com/powerman/sqlxx v0.2.0/go.mod h1:dsfudBeSTo0U61OEAC/WS0Ea7qityww7jvFvWt3U1Fw=
github.com/powerman/structlog v0.7.1 h1:68xN/GdxU7SYbXu/7P4RWyK7lKaN7FXjncarf7wO+Wk=
Expand Down
24 changes: 24 additions & 0 deletions internal/apix/ctx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package apix

import "context"

type Ctx = context.Context

type contextKey int

const (
_ contextKey = iota
contextKeyRemoteIP
)

// NewContextWithRemoteIP creates and returns new context containing given
// remoteIP.
func NewContextWithRemoteIP(ctx Ctx, remoteIP string) Ctx {
return context.WithValue(ctx, contextKeyRemoteIP, remoteIP)
}

// FromContext returns values describing request stored in ctx, if any.
func FromContext(ctx Ctx) (remoteIP string) {
remoteIP, _ = ctx.Value(contextKeyRemoteIP).(string)
return
}
2 changes: 2 additions & 0 deletions internal/apix/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package apix provide API-related helpers.
package apix
6 changes: 2 additions & 4 deletions internal/app/contact_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import (

func TestContacts(tt *testing.T) {
t := check.T(tt)
cleanup, a, mockRepo := testNew(t)
defer cleanup()
a, mockRepo := testNew(t)

var (
c1 = app.Contact{ID: 1, Name: "A"}
Expand All @@ -35,8 +34,7 @@ func TestContacts(tt *testing.T) {

func TestAddContact(tt *testing.T) {
t := check.T(tt)
cleanup, a, mockRepo := testNew(t)
defer cleanup()
a, mockRepo := testNew(t)

c1 := app.Contact{Name: "A"}

Expand Down
4 changes: 2 additions & 2 deletions internal/app/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ var (
auth1 = app.Auth{UserID: "1"}
)

func testNew(t *check.C) (func(), *app.App, *app.MockRepo) {
func testNew(t *check.C) (*app.App, *app.MockRepo) {
ctrl := gomock.NewController(t)

mockRepo := app.NewMockRepo(ctrl)
a := app.New(mockRepo, app.Config{})
return ctrl.Finish, a, mockRepo
return a, mockRepo
}
60 changes: 30 additions & 30 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ var all = &struct { //nolint:gochecknoglobals // Config is global anyway.
MySQLAuthLogin appcfg.NotEmptyString `env:"MYSQL_AUTH_LOGIN"`
MySQLAuthPass appcfg.String `env:"MYSQL_AUTH_PASS"`
MySQLDBName appcfg.NotEmptyString `env:"MYSQL_DB"`
MySQLGooseDir appcfg.NotEmptyString
GooseMySQLDir appcfg.NotEmptyString
}{ // Defaults, if any:
AddrHost: appcfg.MustNotEmptyString(def.Hostname),
AddrPort: appcfg.MustPort("8000"),
MetricsAddrPort: appcfg.MustPort("9000"),
MySQLAddrPort: appcfg.MustPort("3306"),
MySQLAuthLogin: appcfg.MustNotEmptyString(def.ProgName),
MySQLDBName: appcfg.MustNotEmptyString(def.ProgName),
MySQLGooseDir: appcfg.MustNotEmptyString("internal/migrations/mysql"),
GooseMySQLDir: appcfg.MustNotEmptyString("internal/migrations/mysql"),
}

// FlagSets for all CLI subcommands which use flags to set config values.
Expand All @@ -65,31 +65,31 @@ func Init(flagsets FlagSets) error {
return err
}

appcfg.AddPFlag(fs.Serve, &all.AddrHost, "host", "host to serve OpenAPI")
appcfg.AddPFlag(fs.Serve, &all.AddrPort, "port", "port to serve OpenAPI")
appcfg.AddPFlag(fs.Serve, &all.MetricsAddrPort, "metrics.port", "port to serve Prometheus metrics")
appcfg.AddPFlag(fs.Serve, &all.MySQLAddrHost, "mysql.host", "host to connect to MySQL")
appcfg.AddPFlag(fs.Serve, &all.MySQLAddrPort, "mysql.port", "port to connect to MySQL")
appcfg.AddPFlag(fs.Serve, &all.MySQLAuthLogin, "mysql.user", "MySQL username")
appcfg.AddPFlag(fs.Serve, &all.MySQLAuthPass, "mysql.pass", "MySQL password")
appcfg.AddPFlag(fs.Serve, &all.MySQLDBName, "mysql.dbname", "MySQL database name")

appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLAddrHost, "mysql.host", "host to connect to MySQL")
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLAddrPort, "mysql.port", "port to connect to MySQL")
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLDBName, "mysql.dbname", "MySQL database name")
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLAuthLogin, "mysql.user", "MySQL username")
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLAuthPass, "mysql.pass", "MySQL password")
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLDBName, "mysql.dbname", "MySQL database name")

appcfg.AddPFlag(fs.Serve, &all.MySQLAddrHost, "mysql.host", "host to connect to MySQL")
appcfg.AddPFlag(fs.Serve, &all.MySQLAddrPort, "mysql.port", "port to connect to MySQL")
appcfg.AddPFlag(fs.Serve, &all.MySQLDBName, "mysql.dbname", "MySQL database name")
appcfg.AddPFlag(fs.Serve, &all.MySQLAuthLogin, "mysql.user", "MySQL username")
appcfg.AddPFlag(fs.Serve, &all.MySQLAuthPass, "mysql.pass", "MySQL password")
appcfg.AddPFlag(fs.Serve, &all.AddrHost, "host", "host to serve OpenAPI")
appcfg.AddPFlag(fs.Serve, &all.AddrPort, "port", "port to serve OpenAPI")
appcfg.AddPFlag(fs.Serve, &all.MetricsAddrPort, "metrics.port", "port to serve Prometheus metrics")

return nil
}

// ServeConfig contains configuration for subcommand.
type ServeConfig struct {
MySQL *mysql.Config
MySQLGooseDir string
Addr netx.Addr
MetricsAddr netx.Addr
APIKeyAdmin string
MySQL *mysql.Config
GooseMySQLDir string
BindAddr netx.Addr
BindMetricsAddr netx.Addr
APIKeyAdmin string
}

// GetServe validates and returns configuration for subcommand.
Expand All @@ -98,15 +98,15 @@ func GetServe() (c *ServeConfig, err error) {

c = &ServeConfig{
MySQL: def.NewMySQLConfig(def.MySQLConfig{
Addr: netx.NewAddr(all.MySQLAddrHost.Value(&err), all.MySQLAddrPort.Value(&err)),
User: all.MySQLAuthLogin.Value(&err),
Pass: all.MySQLAuthPass.Value(&err),
DB: all.MySQLDBName.Value(&err),
Addr: netx.NewAddr(all.MySQLAddrHost.Value(&err), all.MySQLAddrPort.Value(&err)),
DBName: all.MySQLDBName.Value(&err),
User: all.MySQLAuthLogin.Value(&err),
Pass: all.MySQLAuthPass.Value(&err),
}),
MySQLGooseDir: all.MySQLGooseDir.Value(&err),
Addr: netx.NewAddr(all.AddrHost.Value(&err), all.AddrPort.Value(&err)),
MetricsAddr: netx.NewAddr(all.AddrHost.Value(&err), all.MetricsAddrPort.Value(&err)),
APIKeyAdmin: all.APIKeyAdmin.Value(&err),
GooseMySQLDir: all.GooseMySQLDir.Value(&err),
BindAddr: netx.NewAddr(all.AddrHost.Value(&err), all.AddrPort.Value(&err)),
BindMetricsAddr: netx.NewAddr(all.AddrHost.Value(&err), all.MetricsAddrPort.Value(&err)),
APIKeyAdmin: all.APIKeyAdmin.Value(&err),
}
if err != nil {
return nil, appcfg.WrapPErr(err, fs.Serve, all)
Expand All @@ -119,12 +119,12 @@ func GetGooseMySQL() (c *cobrax.GooseMySQLConfig, err error) {

c = &cobrax.GooseMySQLConfig{
MySQL: def.NewMySQLConfig(def.MySQLConfig{
Addr: netx.NewAddr(all.MySQLAddrHost.Value(&err), all.MySQLAddrPort.Value(&err)),
User: all.MySQLAuthLogin.Value(&err),
Pass: all.MySQLAuthPass.Value(&err),
DB: all.MySQLDBName.Value(&err),
Addr: netx.NewAddr(all.MySQLAddrHost.Value(&err), all.MySQLAddrPort.Value(&err)),
DBName: all.MySQLDBName.Value(&err),
User: all.MySQLAuthLogin.Value(&err),
Pass: all.MySQLAuthPass.Value(&err),
}),
MySQLGooseDir: all.MySQLGooseDir.Value(&err),
GooseMySQLDir: all.GooseMySQLDir.Value(&err),
}
if err != nil {
return nil, appcfg.WrapPErr(err, fs.GooseMySQL, all)
Expand Down
40 changes: 20 additions & 20 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ import (
func Test(t *testing.T) {
want := &ServeConfig{
MySQL: def.NewMySQLConfig(def.MySQLConfig{
Addr: netx.NewAddr("localhost", 3306),
User: "config",
Pass: "",
DB: "config",
Addr: netx.NewAddr("localhost", 3306),
DBName: "config",
User: "config",
Pass: "",
}),
MySQLGooseDir: "internal/migrations/mysql",
Addr: netx.NewAddr(def.Hostname, 8000),
MetricsAddr: netx.NewAddr(def.Hostname, 9000),
APIKeyAdmin: "admin",
GooseMySQLDir: "internal/migrations/mysql",
BindAddr: netx.NewAddr(def.Hostname, 8000),
BindMetricsAddr: netx.NewAddr(def.Hostname, 9000),
APIKeyAdmin: "admin",
}

t.Run("required", func(tt *testing.T) {
Expand Down Expand Up @@ -62,13 +62,13 @@ func Test(t *testing.T) {
c, err := testGetServe()
t.Nil(err)
want.MySQL = def.NewMySQLConfig(def.MySQLConfig{
Addr: netx.NewAddr("mysql3", 33306),
User: "user3",
Pass: "pass3",
DB: "db3",
Addr: netx.NewAddr("mysql3", 33306),
DBName: "db3",
User: "user3",
Pass: "pass3",
})
want.Addr = netx.NewAddr("localhost3", 8003)
want.MetricsAddr = netx.NewAddr("localhost3", 9003)
want.BindAddr = netx.NewAddr("localhost3", 8003)
want.BindMetricsAddr = netx.NewAddr("localhost3", 9003)
want.APIKeyAdmin = "admin3"
t.DeepEqual(c, want)
})
Expand All @@ -86,13 +86,13 @@ func Test(t *testing.T) {
)
t.Nil(err)
want.MySQL = def.NewMySQLConfig(def.MySQLConfig{
Addr: netx.NewAddr("mysql4", 43306),
User: "user4",
Pass: "pass4",
DB: "db4",
Addr: netx.NewAddr("mysql4", 43306),
DBName: "db4",
User: "user4",
Pass: "pass4",
})
want.Addr = netx.NewAddr("localhost4", 8004)
want.MetricsAddr = netx.NewAddr("localhost4", 9004)
want.BindAddr = netx.NewAddr("localhost4", 8004)
want.BindMetricsAddr = netx.NewAddr("localhost4", 9004)
t.DeepEqual(c, want)
})
t.Run("cleanup", func(tt *testing.T) {
Expand Down
Loading

0 comments on commit 7c7c69f

Please sign in to comment.