[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
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -153,7 +151,7 @@ var startCmd = &cobra.Command{
|
|||
printStores(true)
|
||||
}
|
||||
|
||||
srv, err := service.Start()
|
||||
srv, err := service.Start(config.Conf)
|
||||
|
||||
// Start server
|
||||
go func() {
|
||||
|
|
@ -170,11 +168,9 @@ var startCmd = &cobra.Command{
|
|||
for {
|
||||
select {
|
||||
case <-interrupt:
|
||||
ctx, canceled := context.WithTimeout(context.Background(), (5 * time.Second))
|
||||
defer canceled()
|
||||
service.StopWithContext(ctx, func() {
|
||||
fmt.Println(color.GreenString(L("✨STOPPED✨")))
|
||||
})
|
||||
// ctx, canceled := context.WithTimeout(context.Background(), (5 * time.Second))
|
||||
// defer canceled()
|
||||
service.Stop(srv)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
|
@ -245,7 +246,33 @@ func loadApp(root string) error {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import (
|
|||
"github.com/yaoapp/kun/any"
|
||||
"github.com/yaoapp/kun/maps"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/service"
|
||||
)
|
||||
|
||||
func TestCommandVersion(t *testing.T) {
|
||||
|
|
@ -41,7 +40,7 @@ func TestCommandStart(t *testing.T) {
|
|||
oldArgs := os.Args
|
||||
defer func() {
|
||||
os.Args = oldArgs
|
||||
service.Stop(func() {})
|
||||
// service.Stop(func() {})
|
||||
log.Println("服务已关闭")
|
||||
}()
|
||||
|
||||
|
|
@ -129,7 +128,7 @@ func TestCommandStop(t *testing.T) {
|
|||
assert.Equal(t, "管理员", res.Get("name"))
|
||||
|
||||
// 测试关闭
|
||||
service.Stop(func() { log.Println("服务已关闭") })
|
||||
// service.Stop(func() { log.Println("服务已关闭") })
|
||||
time.Sleep(time.Second * 5)
|
||||
_, err = request()
|
||||
assert.NotNil(t, err)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/yao/share"
|
||||
)
|
||||
|
||||
// Middlewares 服务中间件
|
||||
|
|
@ -22,30 +21,21 @@ func BinStatic(c *gin.Context) {
|
|||
c.Next()
|
||||
return
|
||||
|
||||
} else if share.App.XGen == "1.0" {
|
||||
}
|
||||
|
||||
// Xgen 1.0
|
||||
if length >= AdminRootLen && c.Request.URL.Path[0:AdminRootLen] == AdminRoot {
|
||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, c.Request.URL.Path[0:AdminRootLen-1])
|
||||
XGenFileServerV1.ServeHTTP(c.Writer, c.Request)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if length >= 18 && c.Request.URL.Path[0:18] == "/__yao_admin_root/" {
|
||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, "/__yao_admin_root")
|
||||
XGenFileServerV1.ServeHTTP(c.Writer, c.Request)
|
||||
c.Abort()
|
||||
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)
|
||||
// Xgen 1.0
|
||||
if length >= AdminRootLen && c.Request.URL.Path[0:AdminRootLen] == AdminRoot {
|
||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, c.Request.URL.Path[0:AdminRootLen-1])
|
||||
XGenFileServerV1.ServeHTTP(c.Writer, c.Request)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if length >= 18 && c.Request.URL.Path[0:18] == "/__yao_admin_root/" {
|
||||
c.Request.URL.Path = strings.TrimPrefix(c.Request.URL.Path, "/__yao_admin_root")
|
||||
XGenFileServerV1.ServeHTTP(c.Writer, c.Request)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
// 应用内静态文件目录(/ui or public)
|
||||
|
|
|
|||
|
|
@ -1,22 +1,21 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/yaoapp/gou/api"
|
||||
"github.com/yaoapp/gou/server/http"
|
||||
"github.com/yaoapp/kun/log"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"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)
|
||||
|
||||
// Start 启动服务
|
||||
func Start() (*http.Server, error) {
|
||||
if cfg.AllowFrom == nil {
|
||||
cfg.AllowFrom = []string{}
|
||||
}
|
||||
|
||||
err := prepare()
|
||||
if err != nil {
|
||||
|
|
@ -24,64 +23,46 @@ func Start() (*http.Server, error) {
|
|||
}
|
||||
|
||||
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{
|
||||
Host: config.Conf.Host,
|
||||
Port: config.Conf.Port,
|
||||
Root: "/api",
|
||||
Allows: config.Conf.AllowFrom,
|
||||
Host: cfg.Host,
|
||||
Port: cfg.Port,
|
||||
Root: "/api",
|
||||
Allows: cfg.AllowFrom,
|
||||
Timeout: 5 * time.Second,
|
||||
}).With(Middlewares...)
|
||||
|
||||
go func() {
|
||||
err = srv.Start()
|
||||
}()
|
||||
|
||||
return srv, nil
|
||||
}
|
||||
|
||||
// StartWithouttSession 启动服务
|
||||
func StartWithouttSession() (*http.Server, error) {
|
||||
|
||||
router := gin.New()
|
||||
api.SetRoutes(router, "/api", config.Conf.AllowFrom...)
|
||||
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()
|
||||
// Stop the yao service
|
||||
func Stop(srv *http.Server) error {
|
||||
err := srv.Stop()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
<-srv.Event()
|
||||
return nil
|
||||
}
|
||||
|
||||
// StopWithContext stop with timeout
|
||||
func StopWithContext(ctx context.Context, onComplete func()) {
|
||||
shutdown <- true
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Error("[STOP] canceled (%v)", ctx.Err())
|
||||
onComplete()
|
||||
case <-shutdownComplete:
|
||||
share.SessionStop()
|
||||
onComplete()
|
||||
}
|
||||
}
|
||||
// func StopWithContext(ctx context.Context, onComplete func()) {
|
||||
// shutdown <- true
|
||||
// select {
|
||||
// case <-ctx.Done():
|
||||
// log.Error("[STOP] canceled (%v)", ctx.Err())
|
||||
// onComplete()
|
||||
// case <-shutdownComplete:
|
||||
// share.SessionStop()
|
||||
// onComplete()
|
||||
// }
|
||||
// }
|
||||
|
||||
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
|
||||
var AppFileServer http.Handler
|
||||
|
||||
// XGenFileServerV0 XGen v0.9
|
||||
var XGenFileServerV0 http.Handler = http.FileServer(data.XgenV0())
|
||||
|
||||
// XGenFileServerV1 XGen v1.0
|
||||
var XGenFileServerV1 http.Handler = http.FileServer(data.XgenV1())
|
||||
|
||||
|
|
@ -41,9 +38,6 @@ func SetupStatic() error {
|
|||
|
||||
// Static file server
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
|
|
@ -262,12 +261,12 @@ func watchReload(root string, file string, event string, cfg config.Config) {
|
|||
}
|
||||
|
||||
// Restart Server
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
// ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
// defer cancel()
|
||||
|
||||
StopWithContext(ctx, func() {
|
||||
go Start()
|
||||
fmt.Println(color.GreenString("[Watch] Reload Completed"))
|
||||
})
|
||||
// Stop(func() {
|
||||
// go Start()
|
||||
// fmt.Println(color.GreenString("[Watch] Reload Completed"))
|
||||
// })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ func TestWatch(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestWatchReload(t *testing.T) {
|
||||
go Start()
|
||||
defer Stop(func() {})
|
||||
go Start(config.Conf)
|
||||
// defer Stop(func() {})
|
||||
share.DBConnect(config.Conf.DB)
|
||||
watchReload("", "", "", config.Conf)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue