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