package ngs import ( "fmt" "git.noahlan.cn/northlan/ngs/cluster" "git.noahlan.cn/northlan/ngs/component" "git.noahlan.cn/northlan/ngs/internal/env" "git.noahlan.cn/northlan/ngs/internal/log" "git.noahlan.cn/northlan/ngs/internal/runtime" "git.noahlan.cn/northlan/ngs/scheduler" "os" "os/signal" "path/filepath" "strings" "sync/atomic" "syscall" "time" ) var running int32 var ( // app represents the current server process app = &struct { name string // current application name startAt time.Time // startup time }{} ) // Listen listens on the TCP network address addr // and then calls Serve with handler to handle requests // on incoming connections. func Listen(addr string, opts ...Option) { if atomic.AddInt32(&running, 1) != 1 { log.Println("Ngs has running") return } // application initialize app.name = strings.TrimLeft(filepath.Base(os.Args[0]), "/") app.startAt = time.Now() // environment initialize if wd, err := os.Getwd(); err != nil { panic(err) } else { env.Wd, _ = filepath.Abs(wd) } opt := cluster.Options{ Components: &component.Components{}, } for _, option := range opts { option(&opt) } // Use listen address as client address in non-cluster mode if !opt.IsMaster && opt.AdvertiseAddr == "" && opt.ClientAddr == "" { log.Println("The current server running in singleton mode") opt.ClientAddr = addr } // Set the retry interval to 3 secondes if doesn't set by user if opt.RetryInterval == 0 { opt.RetryInterval = time.Second * 3 } node := &cluster.Node{ Options: opt, ServiceAddr: addr, } err := node.Startup() if err != nil { log.Fatalf("Node startup failed: %v", err) } runtime.CurrentNode = node if node.ClientAddr != "" { log.Println(fmt.Sprintf("Startup *Ngs gate server* %s, client address: %v, service address: %s", app.name, node.ClientAddr, node.ServiceAddr)) } else { log.Println(fmt.Sprintf("Startup *Ngs backend server* %s, service address %s", app.name, node.ServiceAddr)) } go scheduler.Schedule() sg := make(chan os.Signal) signal.Notify(sg, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGKILL, syscall.SIGTERM) select { case <-env.Die: log.Println("The app will shutdown in a few seconds") case s := <-sg: log.Println("Ngs server got signal", s) } log.Println("Ngs server is stopping...") node.Shutdown() runtime.CurrentNode = nil scheduler.Close() atomic.StoreInt32(&running, 0) } // Shutdown send a signal to let 'ngs' shutdown itself. func Shutdown() { close(env.Die) }