|
|
|
// Copyright 2022 ROC. All rights reserved.
|
|
|
|
// Use of this source code is governed by a MIT style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/fatih/color"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
"github.com/rocboss/paopao-ce/internal/conf"
|
|
|
|
"github.com/rocboss/paopao-ce/pkg/util"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
httpServers = newServerPool[*httpServer]()
|
|
|
|
grpcServers = newServerPool[*grpcServer]()
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
actOnStart byte = iota
|
|
|
|
actOnStop
|
|
|
|
actStart
|
|
|
|
actStop
|
|
|
|
)
|
|
|
|
|
|
|
|
type server interface {
|
|
|
|
start() error
|
|
|
|
stop() error
|
|
|
|
services() []Service
|
|
|
|
}
|
|
|
|
|
|
|
|
type serverPool[T server] struct {
|
|
|
|
servers map[string]T
|
|
|
|
}
|
|
|
|
|
|
|
|
type baseServer struct {
|
|
|
|
ss map[string]Service
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *serverPool[T]) from(addr string, newServer func() T) T {
|
|
|
|
s, exist := p.servers[addr]
|
|
|
|
if exist {
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
s = newServer()
|
|
|
|
p.servers[addr] = s
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *serverPool[T]) startServer(wg *sync.WaitGroup, maxSidSize int) {
|
|
|
|
for _, srv := range p.servers {
|
|
|
|
wg.Add(1)
|
|
|
|
go func(t T) {
|
|
|
|
ss := t.services()
|
|
|
|
if len(ss) < 1 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, s := range ss {
|
|
|
|
colorPrint(actOnStart, s.OnStart(), maxSidSize, s)
|
|
|
|
}
|
|
|
|
colorPrint(actStart, t.start(), maxSidSize, ss...)
|
|
|
|
// remember to done sync.WaitGroup
|
|
|
|
wg.Done()
|
|
|
|
}(srv)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *serverPool[T]) stopServer(maxSidSize int) {
|
|
|
|
for _, srv := range p.servers {
|
|
|
|
ss := srv.services()
|
|
|
|
if len(ss) < 1 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, s := range ss {
|
|
|
|
colorPrint(actOnStop, s.OnStop(), maxSidSize, s)
|
|
|
|
}
|
|
|
|
colorPrint(actStop, srv.stop(), maxSidSize, ss...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *serverPool[T]) allServices() (ss []Service) {
|
|
|
|
for _, srv := range p.servers {
|
|
|
|
ss = append(ss, srv.services()...)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *baseServer) addService(srv Service) {
|
|
|
|
if srv != nil {
|
|
|
|
sid := srv.Name() + "@" + srv.Version().String()
|
|
|
|
s.ss[sid] = srv
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *baseServer) services() (ss []Service) {
|
|
|
|
for _, s := range s.ss {
|
|
|
|
ss = append(ss, s)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func newServerPool[T server]() *serverPool[T] {
|
|
|
|
return &serverPool[T]{
|
|
|
|
servers: make(map[string]T),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func newBaseServe() *baseServer {
|
|
|
|
return &baseServer{
|
|
|
|
ss: make(map[string]Service),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func checkServices() (int, int) {
|
|
|
|
var ss []Service
|
|
|
|
ss = append(ss, httpServers.allServices()...)
|
|
|
|
ss = append(ss, grpcServers.allServices()...)
|
|
|
|
return len(ss), maxSidSize(ss)
|
|
|
|
}
|
|
|
|
|
|
|
|
// maxSidSize max service id string length
|
|
|
|
func maxSidSize(ss []Service) int {
|
|
|
|
length := 0
|
|
|
|
for _, s := range ss {
|
|
|
|
size := len(s.Name() + "@" + s.Version().String())
|
|
|
|
if size > length {
|
|
|
|
length = size
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length
|
|
|
|
}
|
|
|
|
|
|
|
|
func colorPrint(act byte, err error, l int, ss ...Service) {
|
|
|
|
s := ss[0]
|
|
|
|
switch act {
|
|
|
|
case actOnStart:
|
|
|
|
if err == nil {
|
|
|
|
fmt.Fprintf(color.Output, "%s [start] - %s", util.SidStr(s.Name(), s.Version(), l), s)
|
|
|
|
} else {
|
|
|
|
fmt.Fprintf(color.Output, "%s [start] - run OnStart error: %s\n", util.SidStr(s.Name(), s.Version(), l), err)
|
|
|
|
}
|
|
|
|
case actOnStop:
|
|
|
|
if err == nil {
|
|
|
|
fmt.Fprintf(color.Output, "%s [stop] - finish...\n", util.SidStr(s.Name(), s.Version(), l))
|
|
|
|
} else {
|
|
|
|
fmt.Fprintf(color.Output, "%s [stop] - run OnStop error: %s\n", util.SidStr(s.Name(), s.Version(), l), err)
|
|
|
|
}
|
|
|
|
case actStart:
|
|
|
|
if err != nil {
|
|
|
|
for _, s = range ss {
|
|
|
|
fmt.Fprintf(color.Output, "%s [start] - starting server occurs error:: %s\n", util.SidStr(s.Name(), s.Version(), l), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case actStop:
|
|
|
|
if err != nil {
|
|
|
|
for _, s = range ss {
|
|
|
|
fmt.Fprintf(color.Output, "%s [stop] - stopping server occurs error:: %s\n", util.SidStr(s.Name(), s.Version(), l), err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start start all servers
|
|
|
|
func Start(wg *sync.WaitGroup) {
|
|
|
|
srvSize, maxSidSize := checkServices()
|
|
|
|
if srvSize < 1 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// some initialize for server engine
|
|
|
|
gin.SetMode(conf.RunMode())
|
|
|
|
|
|
|
|
// start servers
|
|
|
|
httpServers.startServer(wg, maxSidSize)
|
|
|
|
grpcServers.startServer(wg, maxSidSize)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stop stop all servers
|
|
|
|
func Stop() {
|
|
|
|
srvSize, maxSidSize := checkServices()
|
|
|
|
if srvSize < 1 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
// stop servers
|
|
|
|
httpServers.stopServer(maxSidSize)
|
|
|
|
grpcServers.stopServer(maxSidSize)
|
|
|
|
}
|