[change] refactor the yao service
This commit is contained in:
parent
8761a26d52
commit
75ee709c23
9 changed files with 163 additions and 103 deletions
12
cmd/start.go
12
cmd/start.go
|
|
@ -1,14 +1,12 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
@ -153,7 +151,7 @@ var startCmd = &cobra.Command{
|
||||||
printStores(true)
|
printStores(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
srv, err := service.Start()
|
srv, err := service.Start(config.Conf)
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -170,11 +168,9 @@ var startCmd = &cobra.Command{
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-interrupt:
|
case <-interrupt:
|
||||||
ctx, canceled := context.WithTimeout(context.Background(), (5 * time.Second))
|
// ctx, canceled := context.WithTimeout(context.Background(), (5 * time.Second))
|
||||||
defer canceled()
|
// defer canceled()
|
||||||
service.StopWithContext(ctx, func() {
|
service.Stop(srv)
|
||||||
fmt.Println(color.GreenString(L("✨STOPPED✨")))
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -245,7 +246,33 @@ func loadApp(root string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
application.Load(app)
|
application.Load(app)
|
||||||
return nil
|
|
||||||
|
var info []byte
|
||||||
|
|
||||||
|
// Read app setting
|
||||||
|
if has, _ := application.App.Exists("app.yao"); has {
|
||||||
|
info, err = application.App.Read("app.yao")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if has, _ := application.App.Exists("app.jsonc"); has {
|
||||||
|
info, err = application.App.Read("app.jsonc")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if has, _ := application.App.Exists("app.json"); has {
|
||||||
|
info, err = application.App.Read("app.json")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("app.yao or app.jsonc or app.json does not exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
share.App = share.AppInfo{}
|
||||||
|
return json.Unmarshal(info, &share.App)
|
||||||
}
|
}
|
||||||
|
|
||||||
func printErr(mode, widget string, err error) {
|
func printErr(mode, widget string, err error) {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"github.com/yaoapp/kun/any"
|
"github.com/yaoapp/kun/any"
|
||||||
"github.com/yaoapp/kun/maps"
|
"github.com/yaoapp/kun/maps"
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
"github.com/yaoapp/yao/service"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCommandVersion(t *testing.T) {
|
func TestCommandVersion(t *testing.T) {
|
||||||
|
|
@ -41,7 +40,7 @@ func TestCommandStart(t *testing.T) {
|
||||||
oldArgs := os.Args
|
oldArgs := os.Args
|
||||||
defer func() {
|
defer func() {
|
||||||
os.Args = oldArgs
|
os.Args = oldArgs
|
||||||
service.Stop(func() {})
|
// service.Stop(func() {})
|
||||||
log.Println("服务已关闭")
|
log.Println("服务已关闭")
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -129,7 +128,7 @@ func TestCommandStop(t *testing.T) {
|
||||||
assert.Equal(t, "管理员", res.Get("name"))
|
assert.Equal(t, "管理员", res.Get("name"))
|
||||||
|
|
||||||
// 测试关闭
|
// 测试关闭
|
||||||
service.Stop(func() { log.Println("服务已关闭") })
|
// service.Stop(func() { log.Println("服务已关闭") })
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
_, err = request()
|
_, err = request()
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yaoapp/yao/share"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Middlewares 服务中间件
|
// Middlewares 服务中间件
|
||||||
|
|
@ -22,7 +21,7 @@ func BinStatic(c *gin.Context) {
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
|
|
||||||
} else if share.App.XGen == "1.0" {
|
}
|
||||||
|
|
||||||
// Xgen 1.0
|
// Xgen 1.0
|
||||||
if length >= AdminRootLen && c.Request.URL.Path[0:AdminRootLen] == AdminRoot {
|
if length >= AdminRootLen && c.Request.URL.Path[0:AdminRootLen] == AdminRoot {
|
||||||
|
|
@ -39,15 +38,6 @@ func BinStatic(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if share.App.XGen == "" && length >= 7 && c.Request.URL.Path[0:7] == "/xiang/" {
|
|
||||||
// Xgen 0.9
|
|
||||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, "/xiang")
|
|
||||||
XGenFileServerV0.ServeHTTP(c.Writer, c.Request)
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 应用内静态文件目录(/ui or public)
|
// 应用内静态文件目录(/ui or public)
|
||||||
AppFileServer.ServeHTTP(c.Writer, c.Request)
|
AppFileServer.ServeHTTP(c.Writer, c.Request)
|
||||||
c.Abort()
|
c.Abort()
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/yaoapp/gou/api"
|
"github.com/yaoapp/gou/api"
|
||||||
"github.com/yaoapp/gou/server/http"
|
"github.com/yaoapp/gou/server/http"
|
||||||
"github.com/yaoapp/kun/log"
|
|
||||||
"github.com/yaoapp/yao/config"
|
"github.com/yaoapp/yao/config"
|
||||||
"github.com/yaoapp/yao/share"
|
"github.com/yaoapp/yao/share"
|
||||||
)
|
)
|
||||||
|
|
||||||
var shutdown = make(chan bool, 1)
|
// Start the yao service
|
||||||
|
func Start(cfg config.Config) (*http.Server, error) {
|
||||||
|
|
||||||
var shutdownComplete = make(chan bool, 1)
|
if cfg.AllowFrom == nil {
|
||||||
|
cfg.AllowFrom = []string{}
|
||||||
// Start 启动服务
|
}
|
||||||
func Start() (*http.Server, error) {
|
|
||||||
|
|
||||||
err := prepare()
|
err := prepare()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -24,64 +23,46 @@ func Start() (*http.Server, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
router := gin.New()
|
router := gin.New()
|
||||||
api.SetRoutes(router, "/api", config.Conf.AllowFrom...)
|
api.SetGuards(Guards)
|
||||||
|
api.SetRoutes(router, "/api", cfg.AllowFrom...)
|
||||||
|
|
||||||
srv := http.New(router, http.Option{
|
srv := http.New(router, http.Option{
|
||||||
Host: config.Conf.Host,
|
Host: cfg.Host,
|
||||||
Port: config.Conf.Port,
|
Port: cfg.Port,
|
||||||
Root: "/api",
|
Root: "/api",
|
||||||
Allows: config.Conf.AllowFrom,
|
Allows: cfg.AllowFrom,
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
}).With(Middlewares...)
|
}).With(Middlewares...)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err = srv.Start()
|
||||||
|
}()
|
||||||
|
|
||||||
return srv, nil
|
return srv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartWithouttSession 启动服务
|
// Stop the yao service
|
||||||
func StartWithouttSession() (*http.Server, error) {
|
func Stop(srv *http.Server) error {
|
||||||
|
err := srv.Stop()
|
||||||
router := gin.New()
|
if err != nil {
|
||||||
api.SetRoutes(router, "/api", config.Conf.AllowFrom...)
|
return err
|
||||||
srv := http.New(router, http.Option{
|
|
||||||
Host: config.Conf.Host,
|
|
||||||
Port: config.Conf.Port,
|
|
||||||
Root: "/api",
|
|
||||||
Allows: config.Conf.AllowFrom,
|
|
||||||
}).With(Middlewares...)
|
|
||||||
|
|
||||||
return srv, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StopWithouttSession 关闭服务
|
|
||||||
func StopWithouttSession(onComplete func()) {
|
|
||||||
shutdown <- true
|
|
||||||
select {
|
|
||||||
case <-shutdownComplete:
|
|
||||||
onComplete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop 关闭服务
|
|
||||||
func Stop(onComplete func()) {
|
|
||||||
shutdown <- true
|
|
||||||
select {
|
|
||||||
case <-shutdownComplete:
|
|
||||||
share.SessionStop()
|
|
||||||
share.DBClose()
|
|
||||||
onComplete()
|
|
||||||
}
|
}
|
||||||
|
<-srv.Event()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopWithContext stop with timeout
|
// StopWithContext stop with timeout
|
||||||
func StopWithContext(ctx context.Context, onComplete func()) {
|
// func StopWithContext(ctx context.Context, onComplete func()) {
|
||||||
shutdown <- true
|
// shutdown <- true
|
||||||
select {
|
// select {
|
||||||
case <-ctx.Done():
|
// case <-ctx.Done():
|
||||||
log.Error("[STOP] canceled (%v)", ctx.Err())
|
// log.Error("[STOP] canceled (%v)", ctx.Err())
|
||||||
onComplete()
|
// onComplete()
|
||||||
case <-shutdownComplete:
|
// case <-shutdownComplete:
|
||||||
share.SessionStop()
|
// share.SessionStop()
|
||||||
onComplete()
|
// onComplete()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
func prepare() error {
|
func prepare() error {
|
||||||
|
|
||||||
|
|
|
||||||
74
service/service_test.go
Normal file
74
service/service_test.go
Normal file
|
|
@ -0,0 +1,74 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/yaoapp/yao/config"
|
||||||
|
"github.com/yaoapp/yao/engine"
|
||||||
|
"github.com/yaoapp/yao/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStartStop(t *testing.T) {
|
||||||
|
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
|
||||||
|
cfg := config.Conf
|
||||||
|
cfg.Port = 0
|
||||||
|
err := engine.Load(cfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
srv, err := Start(cfg)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer Stop(srv)
|
||||||
|
|
||||||
|
<-srv.Event()
|
||||||
|
if !srv.Ready() {
|
||||||
|
t.Fatal("server not ready")
|
||||||
|
}
|
||||||
|
|
||||||
|
port, err := srv.Port()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if port <= 0 {
|
||||||
|
t.Fatal("invalid port")
|
||||||
|
}
|
||||||
|
|
||||||
|
// API Server
|
||||||
|
req := test.NewRequest(port).Route("/api/__yao/app/setting")
|
||||||
|
res, err := req.Get()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, 200, res.Status())
|
||||||
|
data, err := res.Map()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, "Demo Application", data["name"])
|
||||||
|
|
||||||
|
// Public
|
||||||
|
req = test.NewRequest(port).Route("/")
|
||||||
|
res, err = req.Get()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, 200, res.Status())
|
||||||
|
assert.Equal(t, "Hello World\n", res.Body())
|
||||||
|
|
||||||
|
// XGEN
|
||||||
|
req = test.NewRequest(port).Route("/admin/")
|
||||||
|
res, err = req.Get()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, 200, res.Status())
|
||||||
|
assert.Contains(t, res.Body(), "ROOT /admin/")
|
||||||
|
}
|
||||||
|
|
@ -18,9 +18,6 @@ import (
|
||||||
// AppFileServer static file server
|
// AppFileServer static file server
|
||||||
var AppFileServer http.Handler
|
var AppFileServer http.Handler
|
||||||
|
|
||||||
// XGenFileServerV0 XGen v0.9
|
|
||||||
var XGenFileServerV0 http.Handler = http.FileServer(data.XgenV0())
|
|
||||||
|
|
||||||
// XGenFileServerV1 XGen v1.0
|
// XGenFileServerV1 XGen v1.0
|
||||||
var XGenFileServerV1 http.Handler = http.FileServer(data.XgenV1())
|
var XGenFileServerV1 http.Handler = http.FileServer(data.XgenV1())
|
||||||
|
|
||||||
|
|
@ -41,9 +38,6 @@ func SetupStatic() error {
|
||||||
|
|
||||||
// Static file server
|
// Static file server
|
||||||
AppFileServer = http.FileServer(Dir(filepath.Join(config.Conf.Root, "public")))
|
AppFileServer = http.FileServer(Dir(filepath.Join(config.Conf.Root, "public")))
|
||||||
if share.App.XGen == "" || share.App.XGen == "0.9" {
|
|
||||||
AppFileServer = http.FileServer(Dir(filepath.Join(config.Conf.Root, "ui")))
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -262,12 +261,12 @@ func watchReload(root string, file string, event string, cfg config.Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restart Server
|
// Restart Server
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
// defer cancel()
|
||||||
|
|
||||||
StopWithContext(ctx, func() {
|
// Stop(func() {
|
||||||
go Start()
|
// go Start()
|
||||||
fmt.Println(color.GreenString("[Watch] Reload Completed"))
|
// fmt.Println(color.GreenString("[Watch] Reload Completed"))
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ func TestWatch(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWatchReload(t *testing.T) {
|
func TestWatchReload(t *testing.T) {
|
||||||
go Start()
|
go Start(config.Conf)
|
||||||
defer Stop(func() {})
|
// defer Stop(func() {})
|
||||||
share.DBConnect(config.Conf.DB)
|
share.DBConnect(config.Conf.DB)
|
||||||
watchReload("", "", "", config.Conf)
|
watchReload("", "", "", config.Conf)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue