123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- package comm
- import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "os"
- "path"
- "path/filepath"
- "strconv"
- "strings"
- "github.com/jessevdk/go-flags"
- "github.com/kardianos/osext"
- "github.com/nats-io/nats.go"
- "github.com/spf13/viper"
- )
- type AppRootOption struct {
- Version string `short:"v" long:"version" description:"conf version"`
- NatsPort int `short:"p" long:"port" description:"conf nats port"`
- Data string `short:"d" long:"data" description:"conf data dir"`
- Socket int `short:"s" long:"socket" description:"config quit tcp socket"`
- }
- type SysBusProfile struct {
- NatsWsPort int
- NatsPort int
- MiniPort int
- DbPort int
- }
- func (o *AppRootOption) Parse() {
- flags.NewParser(o, flags.Default|flags.IgnoreUnknown).Parse()
- }
- var GAppOption = &AppRootOption{Data: "./data", Version: "0.0.0"}
- type AppRoot struct {
- ExeDir string
- DataDir string
- Name string
- ExitCode int
- RunExe func(func()) error
- OnQuitExe func()
- Quit chan struct{}
- HttpPort int
- NatsWsPort int
- NatsPort int
- ConfYaml string
- ParseConfig func(*viper.Viper) error
- Open func() error
- SysBus SysBusProfile
- Bus *NatsBus
- }
- func (a *AppRoot) InitBus(bus *NatsBus) error {
- fpath := path.Join(filepath.Dir(a.ExeDir), fmt.Sprintf("%s.exe", a.Name))
- appId := GetAppPathId(fpath)
- fmt.Println("app id==========", appId, fpath)
- p, e := bus.RequestConfig("sysbus.profile")
- if e != nil {
- fmt.Println("获取配置失败!", e)
- return e
- }
- e = json.Unmarshal([]byte(p), &a.SysBus)
- if e != nil {
- fmt.Println("解析配置失败!", e)
- return e
- }
- a.NatsWsPort = a.SysBus.NatsWsPort
- _, e = bus.QueueSubscribe(&SubOption{
- Sub: "app.quit." + appId,
- Call: func(obj interface{}, msg *nats.Msg) interface{} {
- a.QuitApp(0)
- return "ok"
- },
- })
- if e != nil {
- return e
- }
- _, e = bus.QueueSubscribe(&SubOption{
- Sub: "app.open." + appId,
- Call: func(obj interface{}, msg *nats.Msg) interface{} {
- d := NatsResponse{ErrorNo: 400}
- if a.Open == nil {
- d.ErrorDesc = "当前应用不能打开"
- } else {
- e := a.Open()
- if e != nil {
- d.ErrorDesc = e.Error()
- } else {
- d.ErrorNo = 200
- d.ErrorDesc = ""
- }
- }
- return d
- },
- })
- if e != nil {
- return e
- }
- e = LancherClientRun(bus, fpath, path.Join(a.ExeDir, "app.yaml"), "")
- if e != nil {
- return e
- }
- a.Bus = bus
- return nil
- }
- func (a *AppRoot) QuitApp(exit int) {
- if a.OnQuitExe != nil {
- a.OnQuitExe()
- a.OnQuitExe = nil
- }
- a.ExitCode = exit
- a.Quit <- struct{}{}
- }
- func (a *AppRoot) GetNatsUrl() string {
- return fmt.Sprintf("nats://localhost:%d", a.NatsPort)
- }
- func (a *AppRoot) GetNatsWebUrl() string {
- return fmt.Sprintf("ws://localhost:%d", a.NatsWsPort)
- }
- func (a *AppRoot) GenHttpPort(d int) int {
- portFile := filepath.Join(a.DataDir, fmt.Sprintf("%s.port", a.Name))
- portStr, err := ioutil.ReadFile(portFile)
- if err == nil && len(portStr) > 0 {
- port, _ := strconv.Atoi(string(portStr))
- if port > 0 {
- return port
- }
- }
- port, _ := GetFreePort()
- if port > 0 {
- d = port
- }
- os.MkdirAll(GAppOption.Data, os.ModePerm)
- ioutil.WriteFile(portFile, []byte(fmt.Sprintf("%d", d)), os.ModePerm)
- return d
- }
- func (a *AppRoot) Run() {
- GAppOption.Parse()
- e := InitQuitSocket(GAppOption.Socket)
- if e != nil {
- fmt.Println(e)
- return
- }
- //go run . 执行
- f, _ := osext.ExecutableFolder()
- exeFoloder := ""
- if strings.LastIndex(f, "\\go-build") == -1 {
- exeFoloder = f
- }
- a.ExeDir = exeFoloder
- a.HttpPort = a.GenHttpPort(20000)
- a.DataDir = GAppOption.Data
- a.NatsPort = GAppOption.NatsPort
- cfile := filepath.Join(exeFoloder, "app.yaml")
- a.ConfYaml = cfile
- if isExist(cfile) && a.ParseConfig != nil {
- file, err := os.Open(cfile)
- if err != nil {
- fmt.Println("open app.yaml error=>", cfile, err)
- return
- }
- v := viper.New()
- v.SetConfigType("yaml")
- err = v.ReadConfig(file)
- if err != nil {
- fmt.Println("read app.yaml error=>", cfile, err)
- return
- }
- err = a.ParseConfig(v)
- if err != nil {
- fmt.Println("parse config error=>", err)
- return
- }
- }
- a.Quit = make(chan struct{})
- defer func() {
- if r := recover(); r != nil {
- fmt.Println("系统异常", r)
- a.QuitApp(500)
- }
- }()
- //开启一个线程跑主要流畅
- go func() {
- err := a.RunExe(func() {
- fmt.Printf("%s started\n", a.Name)
- fmt.Printf("%s is running\n", a.Name)
- })
- if err != nil {
- fmt.Println(a.Name, " running error=>", err)
- a.ExitCode = 1
- a.Quit <- struct{}{}
- } else {
- <-QuitChan
- a.QuitApp(0)
- }
- }()
- <-a.Quit
- if a.OnQuitExe != nil {
- a.OnQuitExe()
- }
- fmt.Println(a.Name, " System Quited")
- if a.ExitCode > 0 {
- os.Exit(a.ExitCode)
- }
- if a.Bus != nil {
- LancherClientQuitApp(a.Bus)
- }
- }
- func isExist(path string) bool {
- _, err := os.Stat(path)
- if err != nil {
- if os.IsExist(err) {
- return true
- }
- if os.IsNotExist(err) {
- return false
- }
- return false
- }
- return true
- }
- var GApp = &AppRoot{}
|