优化最小服务
This commit is contained in:
parent
281b44f637
commit
57c134b6ba
|
@ -36,7 +36,7 @@ func (s *subServer) Start(ctx context.Context) (err error) {
|
|||
[]string{"SSS", "aaa"},
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
kos.Command().Handle("/users", "test command", func(ctx *cli.Context) (err error) {
|
||||
return ctx.Success([]*users{
|
||||
{Name: "Zhan", Age: 10, Tags: []string{"a", "b"}},
|
||||
|
|
|
@ -191,8 +191,12 @@ func serializeArray(val []any) (buf []byte, err error) {
|
|||
row := make([]any, 0, rv.Type().NumField())
|
||||
for j := 0; j < rv.Type().NumField(); j++ {
|
||||
st := rv.Type().Field(j).Tag
|
||||
if columnName, ok = st.Lookup("name"); !ok {
|
||||
if columnName, ok = st.Lookup("kos"); !ok {
|
||||
columnName = strings.ToUpper(rv.Type().Field(j).Name)
|
||||
} else {
|
||||
if columnName == "-" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
row = append(row, columnName)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"git.nspix.com/golang/kos/util/env"
|
||||
|
@ -29,6 +30,7 @@ type Server struct {
|
|||
middleware []Middleware
|
||||
router *Router
|
||||
l net.Listener
|
||||
exitFlag int32
|
||||
}
|
||||
|
||||
func (svr *Server) applyContext() *Context {
|
||||
|
@ -200,10 +202,14 @@ func (svr *Server) Serve(l net.Listener) (err error) {
|
|||
return ctx.Success(svr.router.String())
|
||||
})
|
||||
svr.serve()
|
||||
atomic.StoreInt32(&svr.exitFlag, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func (svr *Server) Shutdown() (err error) {
|
||||
if !atomic.CompareAndSwapInt32(&svr.exitFlag, 0, 1) {
|
||||
return
|
||||
}
|
||||
err = svr.l.Close()
|
||||
svr.ctxMap.Range(func(key, value any) bool {
|
||||
if ctx, ok := value.(*Context); ok {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -26,6 +27,7 @@ type Server struct {
|
|||
fileSystem http.FileSystem
|
||||
beforeRequests []HandleFunc
|
||||
anyRequests map[string]http.Handler
|
||||
exitFlag int32
|
||||
}
|
||||
|
||||
func (svr *Server) applyContext() *Context {
|
||||
|
@ -216,10 +218,14 @@ func (svr *Server) Serve(l net.Listener) (err error) {
|
|||
}
|
||||
svr.router.NotFound = NotFound{}
|
||||
svr.router.MethodNotAllowed = NotAllowed{}
|
||||
atomic.StoreInt32(&svr.exitFlag, 0)
|
||||
return svr.serve.Serve(l)
|
||||
}
|
||||
|
||||
func (svr *Server) Shutdown() (err error) {
|
||||
if !atomic.CompareAndSwapInt32(&svr.exitFlag, 0, 1) {
|
||||
return
|
||||
}
|
||||
if svr.serve != nil {
|
||||
err = svr.serve.Shutdown(svr.ctx)
|
||||
}
|
||||
|
|
60
instance.go
60
instance.go
|
@ -19,53 +19,59 @@ var (
|
|||
std *application
|
||||
)
|
||||
|
||||
func initApplication(cbs ...Option) {
|
||||
func initialization(cbs ...Option) {
|
||||
once.Do(func() {
|
||||
std = New(cbs...)
|
||||
})
|
||||
}
|
||||
|
||||
func Init(cbs ...Option) *application {
|
||||
initApplication(cbs...)
|
||||
func Init(cbs ...Option) Application {
|
||||
initialization(cbs...)
|
||||
return std
|
||||
}
|
||||
|
||||
func Name() string {
|
||||
initialization()
|
||||
return std.opts.Name
|
||||
}
|
||||
|
||||
func ShortName() string {
|
||||
initialization()
|
||||
return std.opts.ShortName()
|
||||
}
|
||||
|
||||
func Version() string {
|
||||
initialization()
|
||||
return std.opts.Version
|
||||
}
|
||||
|
||||
func Debug(args ...any) bool {
|
||||
initialization()
|
||||
if len(args) <= 0 {
|
||||
return std.opts.EnableDebug
|
||||
}
|
||||
if b, ok := args[0].(bool); ok {
|
||||
std.opts.EnableDebug = b
|
||||
}
|
||||
return std.opts.EnableDebug
|
||||
}
|
||||
|
||||
func Node() *Info {
|
||||
initApplication()
|
||||
initialization()
|
||||
return std.Info()
|
||||
}
|
||||
|
||||
func Http() *http.Server {
|
||||
initApplication()
|
||||
initialization()
|
||||
return std.Http()
|
||||
}
|
||||
|
||||
func Name() string {
|
||||
initApplication()
|
||||
return std.opts.Name
|
||||
}
|
||||
|
||||
func Version() string {
|
||||
initApplication()
|
||||
return std.opts.Version
|
||||
}
|
||||
|
||||
func Debug() bool {
|
||||
initApplication()
|
||||
return std.opts.EnableDebug
|
||||
}
|
||||
|
||||
func Command() *cli.Server {
|
||||
initApplication()
|
||||
initialization()
|
||||
return std.Command()
|
||||
}
|
||||
|
||||
func ShortName() string {
|
||||
initApplication()
|
||||
return std.opts.ShortName()
|
||||
}
|
||||
|
||||
func Handle(method string, cb HandleFunc) {
|
||||
initApplication()
|
||||
initialization()
|
||||
std.Handle(method, cb)
|
||||
}
|
||||
|
|
11
options.go
11
options.go
|
@ -18,10 +18,11 @@ type (
|
|||
Address string //绑定地址
|
||||
Port int //端口
|
||||
EnableDebug bool //开启调试模式
|
||||
DisableGateway bool //禁用HTTP和COMMAND入口
|
||||
DisableHttp bool //禁用HTTP入口
|
||||
EnableDirectHttp bool //启用HTTP直连模式
|
||||
DisableCommand bool //禁用命令行入口
|
||||
EnableDirectCommand bool //启用命令行直连模式
|
||||
DisableCommand bool //禁用COMMAND入口
|
||||
EnableDirectCommand bool //启用COMMAND直连模式
|
||||
DisableStateApi bool //禁用系统状态接口
|
||||
Metadata map[string]string //原数据
|
||||
Context context.Context
|
||||
|
@ -64,6 +65,12 @@ func WithName(name string, version string) Option {
|
|||
}
|
||||
}
|
||||
|
||||
func WithoutGateway() Option {
|
||||
return func(o *Options) {
|
||||
o.DisableGateway = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithPort(port int) Option {
|
||||
return func(o *Options) {
|
||||
o.Port = port
|
||||
|
|
55
service.go
55
service.go
|
@ -94,7 +94,6 @@ func (app *application) httpServe() (err error) {
|
|||
var (
|
||||
l net.Listener
|
||||
)
|
||||
app.http = http.New(app.ctx)
|
||||
if l, err = app.gateway.Apply(
|
||||
entry.Feature(http.MethodGet),
|
||||
entry.Feature(http.MethodHead),
|
||||
|
@ -141,7 +140,6 @@ func (app *application) commandServe() (err error) {
|
|||
var (
|
||||
l net.Listener
|
||||
)
|
||||
app.command = cli.New(app.ctx)
|
||||
if l, err = app.gateway.Apply(
|
||||
cli.Feature,
|
||||
); err != nil {
|
||||
|
@ -213,23 +211,26 @@ func (app *application) preStart() (err error) {
|
|||
app.Log().Infof("server starting")
|
||||
env.Set(EnvAppName, app.opts.ShortName())
|
||||
env.Set(EnvAppVersion, app.opts.Version)
|
||||
addr = net.JoinHostPort(app.opts.Address, strconv.Itoa(app.opts.Port))
|
||||
app.Log().Infof("server listen on: %s", addr)
|
||||
app.gateway = entry.New(addr)
|
||||
if err = app.gateway.Start(app.ctx); err != nil {
|
||||
return
|
||||
}
|
||||
if !app.opts.DisableHttp {
|
||||
if err = app.httpServe(); err != nil {
|
||||
app.http = http.New(app.ctx)
|
||||
app.command = cli.New(app.ctx)
|
||||
if !app.opts.DisableGateway {
|
||||
addr = net.JoinHostPort(app.opts.Address, strconv.Itoa(app.opts.Port))
|
||||
app.Log().Infof("server listen on: %s", addr)
|
||||
app.gateway = entry.New(addr)
|
||||
if err = app.gateway.Start(app.ctx); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if !app.opts.DisableCommand {
|
||||
if err = app.commandServe(); err != nil {
|
||||
return
|
||||
if !app.opts.DisableHttp {
|
||||
if err = app.httpServe(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if !app.opts.DisableCommand {
|
||||
if err = app.commandServe(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
app.plugins.Range(func(key, value any) bool {
|
||||
if plugin, ok := value.(Plugin); ok {
|
||||
if err = plugin.BeforeStart(); err != nil {
|
||||
|
@ -289,18 +290,20 @@ func (app *application) preStop() (err error) {
|
|||
}
|
||||
return true
|
||||
})
|
||||
if app.http != nil {
|
||||
if err = app.http.Shutdown(); err != nil {
|
||||
app.Log().Warnf("server http shutdown error: %s", err.Error())
|
||||
if !app.opts.DisableGateway {
|
||||
if app.http != nil {
|
||||
if err = app.http.Shutdown(); err != nil {
|
||||
app.Log().Warnf("server http shutdown error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
if app.command != nil {
|
||||
if err = app.command.Shutdown(); err != nil {
|
||||
app.Log().Warnf("server command shutdown error: %s", err.Error())
|
||||
if app.command != nil {
|
||||
if err = app.command.Shutdown(); err != nil {
|
||||
app.Log().Warnf("server command shutdown error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
if err = app.gateway.Stop(); err != nil {
|
||||
app.Log().Warnf("server gateway shutdown error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
if err = app.gateway.Stop(); err != nil {
|
||||
app.Log().Warnf("server gateway shutdown error: %s", err.Error())
|
||||
}
|
||||
app.plugins.Range(func(key, value any) bool {
|
||||
if plugin, ok := value.(Plugin); ok {
|
||||
|
@ -345,7 +348,7 @@ func (app *application) Run() (err error) {
|
|||
return app.preStop()
|
||||
}
|
||||
|
||||
func New(cbs ...Option) *application {
|
||||
func New(cbs ...Option) Application {
|
||||
opts := NewOptions(cbs...)
|
||||
app := &application{
|
||||
opts: opts,
|
||||
|
|
1
types.go
1
types.go
|
@ -23,6 +23,7 @@ type (
|
|||
Http() *http.Server
|
||||
Command() *cli.Server
|
||||
Handle(method string, cb HandleFunc, opts ...HandleOption)
|
||||
Run() (err error)
|
||||
}
|
||||
|
||||
// Info application information
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package fs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
|
||||
|
@ -11,22 +10,26 @@ func IsDir(filename string) (bool, error) {
|
|||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
fm := fd.Mode()
|
||||
return fm.IsDir(), nil
|
||||
return fd.Mode().IsDir(), nil
|
||||
}
|
||||
|
||||
// DirectoryOrCreate checking directory, is not exists will create
|
||||
func DirectoryOrCreate(dirname string) error {
|
||||
// IsFile Tells whether the filename is a file
|
||||
func IsFile(filename string) (bool, error) {
|
||||
fd, err := os.Stat(filename)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return !fd.Mode().IsDir(), nil
|
||||
}
|
||||
|
||||
// Mkdir checking directory, is not exists will create
|
||||
func Mkdir(dirname string, perm os.FileMode) error {
|
||||
if fi, err := os.Stat(dirname); err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return os.MkdirAll(dirname, 0755)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
return os.MkdirAll(dirname, perm)
|
||||
} else {
|
||||
if fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
return errors.New("file not directory")
|
||||
return os.ErrPermission
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package fs
|
|
@ -2,19 +2,15 @@ package sys
|
|||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// HomeDir return user home directory
|
||||
func HomeDir() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
return os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
|
||||
if dirname, err := os.UserHomeDir(); err == nil {
|
||||
return dirname
|
||||
}
|
||||
if h := os.Getenv("HOME"); h != "" {
|
||||
return h
|
||||
}
|
||||
return "/"
|
||||
return os.TempDir()
|
||||
}
|
||||
|
||||
// HiddenFile get hidden file prefix
|
||||
|
@ -29,20 +25,12 @@ func HiddenFile(name string) string {
|
|||
|
||||
// CacheDir return user cache directory
|
||||
func CacheDir() string {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
return filepath.Join(HomeDir(), "Library", "Caches")
|
||||
case "windows":
|
||||
for _, ev := range []string{"APPDATA", "CSIDL_APPDATA", "TEMP", "TMP"} {
|
||||
if v := os.Getenv(ev); v != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
// Worst case:
|
||||
return HomeDir()
|
||||
if dirname, err := os.UserCacheDir(); err == nil {
|
||||
return dirname
|
||||
}
|
||||
if xdg := os.Getenv("XDG_CACHE_HOME"); xdg != "" {
|
||||
return xdg
|
||||
}
|
||||
return filepath.Join(HomeDir(), ".cache")
|
||||
return os.TempDir()
|
||||
}
|
||||
|
||||
func TempFile() (*os.File, error) {
|
||||
return os.CreateTemp(os.TempDir(), "kos_*")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue