[change] refactor the yao service

This commit is contained in:
Max 2023-03-26 17:12:02 +08:00
parent 8761a26d52
commit 75ee709c23
9 changed files with 163 additions and 103 deletions

View file

@ -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
}
}

View file

@ -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) {

View file

@ -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)

View file

@ -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)

View file

@ -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
View 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/")
}

View file

@ -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
}

View file

@ -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"))
// })
}
}

View file

@ -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)
}