Skip to content

Commit

Permalink
feat: basic implements for go server
Browse files Browse the repository at this point in the history
  • Loading branch information
gaulzhw committed Dec 4, 2022
1 parent 472e4bb commit 210f07d
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 68 deletions.
14 changes: 13 additions & 1 deletion cmd/server/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,17 @@ func NewServerCommand() *cobra.Command {
}

func run(opts *options.Options) error {
return nil
mysqlClient, err := opts.MySQL.NewClient()
if err != nil {
return err
}

server, err := opts.Server.NewServer()
if err != nil {
return err
}

server.InjectStoreFactory(mysqlClient)

return server.Start()
}
10 changes: 0 additions & 10 deletions internal/options/interface.go

This file was deleted.

62 changes: 60 additions & 2 deletions internal/options/mysql_options.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,80 @@
package options

import (
"fmt"
"time"

"github.com/spf13/pflag"
"gorm.io/driver/mysql"
"gorm.io/gorm"

"github.com/gaulzhw/go-server/internal/store"
mysqlstore "github.com/gaulzhw/go-server/internal/store/mysql"
)

type MySQLOptions struct {
Host string
Username string
Password string
Database string
MaxIdleConnections int
MaxOpenConnections int
MaxConnectionLifeTime time.Duration
}

var _ options = (*MySQLOptions)(nil)

func NewMySQLOptions() *MySQLOptions {
return &MySQLOptions{}
}

func (o *MySQLOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&o.Host, "mysql-host", "127.0.0.1",
"MySQL service host address. Default to 127.0.0.1.")
fs.StringVar(&o.Username, "mysql-username", "root",
"Username for access to mysql service. Default to root.")
fs.StringVar(&o.Password, "mysql-password", "123456",
"Password for access to mysql. Default to 123456.")
fs.StringVar(&o.Database, "mysql-database", "",
"Database name for the server to use. Default to empty.")

fs.IntVar(&o.MaxIdleConnections, "mysql-max-idle-connections", 100,
"Maximum idle connections allowed to connect to mysql. Default to 100.")
fs.IntVar(&o.MaxOpenConnections, "mysql-max-open-connections", 100,
"Maximum open connections allowed to connect to mysql. Default to 100.")
fs.DurationVar(&o.MaxConnectionLifeTime, "mysql-max-connection-life-time", time.Duration(10)*time.Second,
"Maximum connection life time allowed to connect to mysql. Default to 10s.")
}

func (o *MySQLOptions) Validate() []error {
var errs []error
return errs
}

// NewClient create mysql store with the given config.
func (o *MySQLOptions) NewClient() (store.Factory, error) {
dsn := fmt.Sprintf(`%s:%s@tcp(%s)/%s?charset=utf8&parseTime=%t&loc=%s`,
o.Username,
o.Password,
o.Host,
o.Database,
true,
"Local",
)
db, err := gorm.Open(mysql.Open(dsn))
if err != nil {
return nil, err
}

sqlDB, err := db.DB()
if err != nil {
return nil, err
}

// SetMaxOpenConns sets the maximum number of open connections to the database.
sqlDB.SetMaxOpenConns(o.MaxOpenConnections)
// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
sqlDB.SetConnMaxLifetime(o.MaxConnectionLifeTime)
// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
sqlDB.SetMaxIdleConns(o.MaxIdleConnections)

return mysqlstore.NewStore(db)
}
2 changes: 0 additions & 2 deletions internal/options/server_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ type ServerOptions struct {
CertDir string
}

var _ options = (*ServerOptions)(nil)

func NewServerOptions() *ServerOptions {
return &ServerOptions{}
}
Expand Down
27 changes: 27 additions & 0 deletions internal/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ import (
"net/http/pprof"

"github.com/gin-gonic/gin"

"github.com/gaulzhw/go-server/internal/controller/v1/user"
"github.com/gaulzhw/go-server/internal/store"
"github.com/gaulzhw/go-server/pkg/core"
"github.com/gaulzhw/go-server/pkg/errno"
)

type Server struct {
factory store.Factory

httpSrv *http.Server
}

Expand All @@ -27,6 +34,10 @@ func NewServer(addr string, tls *tls.Config) *Server {
}
}

func (s *Server) InjectStoreFactory(factory store.Factory) {
s.factory = factory
}

func (s *Server) Start() error {
// route
s.httpSrv.Handler = s.router()
Expand All @@ -47,6 +58,10 @@ func (s *Server) router() http.Handler {
r := gin.New()
r.Use(gin.Recovery())

r.NoRoute(func(c *gin.Context) {
core.WriteResponse(c, errno.ParseCoder(errno.ErrUnknown.Error()), nil)
})

// pprof
{
r.GET("/debug/pprof/", gin.WrapF(pprof.Index))
Expand All @@ -56,5 +71,17 @@ func (s *Server) router() http.Handler {
r.GET("/debug/pprof/trace", gin.WrapF(pprof.Trace))
}

// middleware
v1 := r.Group("/api/v1")
{
// user RESTful resources
userv1 := v1.Group("/users")
{
userController := user.NewController(s.factory)
userv1.GET(":name", userController.Get)
userv1.POST("", userController.Create)
}
}

return r
}
35 changes: 1 addition & 34 deletions internal/store/mysql/mysql_store.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package mysql

import (
"fmt"

"github.com/pkg/errors"
"gorm.io/driver/mysql"
"gorm.io/gorm"

"github.com/gaulzhw/go-server/internal/store"
Expand Down Expand Up @@ -32,40 +29,10 @@ func (ds *mysqlStore) Close() error {
}

// NewStore create mysql store with the given config.
func NewStore() (store.Factory, error) {
dsn := fmt.Sprintf(`%s:%s@tcp(%s)/%s?charset=utf8&parseTime=%t&loc=%s`,
opts.Username,
opts.Password,
opts.Host,
opts.Database,
true,
"Local",
)
db, err := gorm.Open(mysql.Open(dsn))
if err != nil {
return nil, err
}

sqlDB, err := db.DB()
if err != nil {
return nil, err
}

// SetMaxOpenConns sets the maximum number of open connections to the database.
sqlDB.SetMaxOpenConns(opts.MaxOpenConnections)
// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
sqlDB.SetConnMaxLifetime(opts.MaxConnectionLifeTime)
// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
sqlDB.SetMaxIdleConns(opts.MaxIdleConnections)

func NewStore(db *gorm.DB) (store.Factory, error) {
store := &mysqlStore{
db: db,
user: user.NewStore(db),
}

if store == nil || err != nil {
return nil, errors.WithMessagef(err, "failed to get mysql store, mysqlStore: %+v", store)
}

return store, nil
}
16 changes: 2 additions & 14 deletions internal/store/store.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
package store

var client Factory

// Factory defines the storage interface.
type Factory interface {
Users() User

Close() error
}

// Client return the store client instance.
func Client() Factory {
return client
}

// SetClient set the iam store client.
func SetClient(factory Factory) {
client = factory

Users() User
}
7 changes: 5 additions & 2 deletions pkg/errno/base.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package errno

const (
// SUCCESS - 200: OK.
SUCCESS errorno = iota + 100001
// Success - 200: OK.
Success errorno = iota + 100001

// ErrUnknown - 500: Internal server error.
ErrUnknown

// ErrNotFound - 404: Not found error.
ErrNotFound
)
10 changes: 9 additions & 1 deletion pkg/errno/code.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ import (
)

var (
validCodes = []int{http.StatusOK, http.StatusBadRequest, http.StatusInternalServerError}
validCodes = []int{
http.StatusOK, // 200
http.StatusBadRequest, // 400
http.StatusUnauthorized, // 401
http.StatusPaymentRequired, // 402
http.StatusForbidden, // 403
http.StatusNotFound, // 404
http.StatusInternalServerError, // 500
}

unknownCoder = &errCode{C: 1, HTTP: http.StatusInternalServerError, Ext: "An internal server error occurred"}
)
Expand Down
2 changes: 1 addition & 1 deletion pkg/errno/errno_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/errno/errno_generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

| Identifier | Code | HTTP Code | Description |
| ---------- | ---- | --------- | ----------- |
| SUCCESS | 100001 | 200 | OK |
| Success | 100001 | 200 | OK |
| ErrUnknown | 100002 | 500 | Internal server error |

0 comments on commit 210f07d

Please sign in to comment.