app-root.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package comm
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "os"
  7. "path"
  8. "path/filepath"
  9. "strconv"
  10. "strings"
  11. "github.com/jessevdk/go-flags"
  12. "github.com/kardianos/osext"
  13. "github.com/nats-io/nats.go"
  14. "github.com/spf13/viper"
  15. )
  16. type AppRootOption struct {
  17. Version string `short:"v" long:"version" description:"conf version"`
  18. NatsPort int `short:"p" long:"port" description:"conf nats port"`
  19. Data string `short:"d" long:"data" description:"conf data dir"`
  20. Socket int `short:"s" long:"socket" description:"config quit tcp socket"`
  21. }
  22. type SysBusProfile struct {
  23. NatsWsPort int
  24. NatsPort int
  25. MiniPort int
  26. DbPort int
  27. }
  28. func (o *AppRootOption) Parse() {
  29. flags.NewParser(o, flags.Default|flags.IgnoreUnknown).Parse()
  30. }
  31. var GAppOption = &AppRootOption{Data: "./data", Version: "0.0.0"}
  32. type AppRoot struct {
  33. ExeDir string
  34. DataDir string
  35. Name string
  36. ExitCode int
  37. RunExe func(func()) error
  38. OnQuitExe func()
  39. Quit chan struct{}
  40. HttpPort int
  41. NatsWsPort int
  42. NatsPort int
  43. ConfYaml string
  44. ParseConfig func(*viper.Viper) error
  45. Open func() error
  46. SysBus SysBusProfile
  47. Bus *NatsBus
  48. }
  49. func (a *AppRoot) InitBus(bus *NatsBus) error {
  50. fpath := path.Join(filepath.Dir(a.ExeDir), fmt.Sprintf("%s.exe", a.Name))
  51. appId := GetAppPathId(fpath)
  52. fmt.Println("app id==========", appId, fpath)
  53. p, e := bus.RequestConfig("sysbus.profile")
  54. if e != nil {
  55. fmt.Println("获取配置失败!", e)
  56. return e
  57. }
  58. e = json.Unmarshal([]byte(p), &a.SysBus)
  59. if e != nil {
  60. fmt.Println("解析配置失败!", e)
  61. return e
  62. }
  63. a.NatsWsPort = a.SysBus.NatsWsPort
  64. _, e = bus.QueueSubscribe(&SubOption{
  65. Sub: "app.quit." + appId,
  66. Call: func(obj interface{}, msg *nats.Msg) interface{} {
  67. a.QuitApp(0)
  68. return "ok"
  69. },
  70. })
  71. if e != nil {
  72. return e
  73. }
  74. _, e = bus.QueueSubscribe(&SubOption{
  75. Sub: "app.open." + appId,
  76. Call: func(obj interface{}, msg *nats.Msg) interface{} {
  77. d := NatsResponse{ErrorNo: 400}
  78. if a.Open == nil {
  79. d.ErrorDesc = "当前应用不能打开"
  80. } else {
  81. e := a.Open()
  82. if e != nil {
  83. d.ErrorDesc = e.Error()
  84. } else {
  85. d.ErrorNo = 200
  86. d.ErrorDesc = ""
  87. }
  88. }
  89. return d
  90. },
  91. })
  92. if e != nil {
  93. return e
  94. }
  95. e = LancherClientRun(bus, fpath, path.Join(a.ExeDir, "app.yaml"), "")
  96. if e != nil {
  97. return e
  98. }
  99. a.Bus = bus
  100. return nil
  101. }
  102. func (a *AppRoot) QuitApp(exit int) {
  103. if a.OnQuitExe != nil {
  104. a.OnQuitExe()
  105. a.OnQuitExe = nil
  106. }
  107. a.ExitCode = exit
  108. a.Quit <- struct{}{}
  109. }
  110. func (a *AppRoot) GetNatsUrl() string {
  111. return fmt.Sprintf("nats://localhost:%d", a.NatsPort)
  112. }
  113. func (a *AppRoot) GetNatsWebUrl() string {
  114. return fmt.Sprintf("ws://localhost:%d", a.NatsWsPort)
  115. }
  116. func (a *AppRoot) GenHttpPort(d int) int {
  117. portFile := filepath.Join(a.DataDir, fmt.Sprintf("%s.port", a.Name))
  118. portStr, err := ioutil.ReadFile(portFile)
  119. if err == nil && len(portStr) > 0 {
  120. port, _ := strconv.Atoi(string(portStr))
  121. if port > 0 {
  122. return port
  123. }
  124. }
  125. port, _ := GetFreePort()
  126. if port > 0 {
  127. d = port
  128. }
  129. os.MkdirAll(GAppOption.Data, os.ModePerm)
  130. ioutil.WriteFile(portFile, []byte(fmt.Sprintf("%d", d)), os.ModePerm)
  131. return d
  132. }
  133. func (a *AppRoot) Run() {
  134. GAppOption.Parse()
  135. e := InitQuitSocket(GAppOption.Socket)
  136. if e != nil {
  137. fmt.Println(e)
  138. return
  139. }
  140. //go run . 执行
  141. f, _ := osext.ExecutableFolder()
  142. exeFoloder := ""
  143. if strings.LastIndex(f, "\\go-build") == -1 {
  144. exeFoloder = f
  145. }
  146. a.ExeDir = exeFoloder
  147. a.HttpPort = a.GenHttpPort(20000)
  148. a.DataDir = GAppOption.Data
  149. a.NatsPort = GAppOption.NatsPort
  150. cfile := filepath.Join(exeFoloder, "app.yaml")
  151. a.ConfYaml = cfile
  152. if isExist(cfile) && a.ParseConfig != nil {
  153. file, err := os.Open(cfile)
  154. if err != nil {
  155. fmt.Println("open app.yaml error=>", cfile, err)
  156. return
  157. }
  158. v := viper.New()
  159. v.SetConfigType("yaml")
  160. err = v.ReadConfig(file)
  161. if err != nil {
  162. fmt.Println("read app.yaml error=>", cfile, err)
  163. return
  164. }
  165. err = a.ParseConfig(v)
  166. if err != nil {
  167. fmt.Println("parse config error=>", err)
  168. return
  169. }
  170. }
  171. a.Quit = make(chan struct{})
  172. defer func() {
  173. if r := recover(); r != nil {
  174. fmt.Println("系统异常", r)
  175. a.QuitApp(500)
  176. }
  177. }()
  178. //开启一个线程跑主要流畅
  179. go func() {
  180. err := a.RunExe(func() {
  181. fmt.Printf("%s started\n", a.Name)
  182. fmt.Printf("%s is running\n", a.Name)
  183. })
  184. if err != nil {
  185. fmt.Println(a.Name, " running error=>", err)
  186. a.ExitCode = 1
  187. a.Quit <- struct{}{}
  188. } else {
  189. <-QuitChan
  190. a.QuitApp(0)
  191. }
  192. }()
  193. <-a.Quit
  194. if a.OnQuitExe != nil {
  195. a.OnQuitExe()
  196. }
  197. fmt.Println(a.Name, " System Quited")
  198. if a.ExitCode > 0 {
  199. os.Exit(a.ExitCode)
  200. }
  201. if a.Bus != nil {
  202. LancherClientQuitApp(a.Bus)
  203. }
  204. }
  205. func isExist(path string) bool {
  206. _, err := os.Stat(path)
  207. if err != nil {
  208. if os.IsExist(err) {
  209. return true
  210. }
  211. if os.IsNotExist(err) {
  212. return false
  213. }
  214. return false
  215. }
  216. return true
  217. }
  218. var GApp = &AppRoot{}