217 lines
6.0 KiB
Go
217 lines
6.0 KiB
Go
package node
|
||
|
||
import (
|
||
"admin/lib/xlog"
|
||
"fmt"
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
// Task 不会永久执行的任务,串行用于启动前初始化或者启动后初始化工作,返回error就停止application
|
||
type Task func() error
|
||
|
||
// Worker 永久执行的工作协程,一旦停止就停止application
|
||
type Worker func() error
|
||
|
||
// Job 不会永久执行的任务,且不关心执行结果,不关心执行顺序,例如内存预热等
|
||
type Job func()
|
||
|
||
type pair struct {
|
||
key any
|
||
value any
|
||
}
|
||
|
||
// Application 受scheduler调度的最小逻辑单元,有独立的启动参数、各种串行、并行任务
|
||
type Application struct {
|
||
Name string
|
||
bootFlag interface{}
|
||
initializeTasks []pair // 启动服务前串行执行初始化任务的job
|
||
services []pair // rpc服务
|
||
servers []pair // web服务
|
||
postRunTasks []pair // 启动后串行执行的job
|
||
postRunWorkers []pair // 启动后后台永久执行的工作协程,一旦推出就停止application
|
||
parallelJobs []pair // 启动services、servers后并行执行的任务,不关心结果,例如内存数据的预热等
|
||
stopTasks []pair
|
||
}
|
||
|
||
// newApp
|
||
func newApp(name string, options ...AppOption) *Application {
|
||
app := new(Application)
|
||
app.Name = name
|
||
app.applyOptions(options...)
|
||
return app
|
||
}
|
||
|
||
// WithInitializeTask app完成init之后run之前执行的任务,可以用来初始化某些业务或者检查配置等
|
||
func (app *Application) WithInitializeTask(desc string, task Task) *Application {
|
||
if task == nil {
|
||
return app
|
||
}
|
||
app.initializeTasks = append(app.initializeTasks, pair{desc, task})
|
||
return app
|
||
}
|
||
|
||
// WithServer 添加web服务器
|
||
func (app *Application) WithServer(desc string, addr string) *gin.Engine {
|
||
server := gin.Default()
|
||
app.servers = append(app.servers, pair{desc, pair{addr, server}})
|
||
return server
|
||
}
|
||
|
||
// WithService 添加rpc服务
|
||
//func (app *Application) WithService(desc string, service *joyservice.ServicesManager) *Application {
|
||
// if service == nil {
|
||
// return app
|
||
// }
|
||
// app.services = append(app.services, pair{desc, service})
|
||
// return app
|
||
//}
|
||
|
||
// WithPostTask app run之后执行的任务,一般做临时检查任务,可以用来服务启动后加载数据检查等
|
||
func (app *Application) WithPostTask(desc string, task Task) *Application {
|
||
if task == nil {
|
||
return nil
|
||
}
|
||
app.postRunTasks = append(app.postRunTasks, pair{desc, task})
|
||
return app
|
||
}
|
||
|
||
// WithPostWorker 完成post task之后执行的后台任务,报错退出等app也会退出,一般做永久的关键后台逻辑
|
||
func (app *Application) WithPostWorker(desc string, worker Worker) *Application {
|
||
if worker == nil {
|
||
return app
|
||
}
|
||
app.postRunWorkers = append(app.postRunWorkers, pair{desc, worker})
|
||
return app
|
||
}
|
||
|
||
// WithParallelJob 完成post task之后执行的并行后台任务,一般做永久的不关键后台逻辑,例如内存预热等
|
||
func (app *Application) WithParallelJob(desc string, job Job) *Application {
|
||
if job == nil {
|
||
return app
|
||
}
|
||
app.parallelJobs = append(app.parallelJobs, pair{desc, job})
|
||
return app
|
||
}
|
||
|
||
// WithStopTask 注册停服逻辑(只能处理正常停服,异常例如panic、oom会监听不到)
|
||
func (app *Application) WithStopTask(desc string, task Task) *Application {
|
||
if task == nil {
|
||
return app
|
||
}
|
||
app.stopTasks = append(app.stopTasks, pair{desc, task})
|
||
return app
|
||
}
|
||
|
||
func (app *Application) GetBootConfig() any {
|
||
return app.bootFlag
|
||
}
|
||
|
||
func (app *Application) applyOptions(options ...AppOption) *Application {
|
||
for _, option := range options {
|
||
option.Apply(app)
|
||
}
|
||
return app
|
||
}
|
||
|
||
func (app *Application) run() (err error) {
|
||
waitChan := make(chan error, 1)
|
||
|
||
// 启动前的初始化任务
|
||
for _, j := range app.initializeTasks {
|
||
curErr := j.value.(Task)()
|
||
if curErr != nil {
|
||
err = fmt.Errorf("run initialize task(%s) return error:%v", j.key, curErr)
|
||
return
|
||
}
|
||
}
|
||
|
||
// 启动rpc服务
|
||
//for _, pair := range app.services {
|
||
// go func(desc string, s *joyservice.ServicesManager) {
|
||
// jlog.Noticef("app %v service %v will listen on %v", app.Name, desc, s.Addr)
|
||
// curErr := s.Run()
|
||
// if curErr != nil {
|
||
// waitChan <- fmt.Errorf("service %s run on %v error:%v", desc, s.Addr, curErr)
|
||
// } else {
|
||
//
|
||
// }
|
||
// }(pair.desc, pair.item.(*joyservice.ServicesManager))
|
||
//}
|
||
|
||
//defer app.stopServices()
|
||
|
||
// 启动web服务
|
||
for _, server := range app.servers {
|
||
go func(desc string, info pair) {
|
||
addr := info.key.(string)
|
||
engine := info.value.(*gin.Engine)
|
||
xlog.Noticef("app %v server %v will listen on %v", app.Name, desc, addr)
|
||
err := engine.Run(addr)
|
||
if err != nil {
|
||
waitChan <- fmt.Errorf("server %s error:%v", desc, err)
|
||
} else {
|
||
|
||
}
|
||
}(server.key.(string), server.value.(pair))
|
||
}
|
||
|
||
//defer app.stopServers()
|
||
|
||
// 启动后串行执行的job
|
||
for _, j := range app.postRunTasks {
|
||
curErr := j.value.(Task)()
|
||
if curErr != nil {
|
||
err = fmt.Errorf("run post task %s return error:%v", j.key, curErr)
|
||
return
|
||
}
|
||
}
|
||
|
||
// 启动后串行执行的工作协程
|
||
for _, worker := range app.postRunWorkers {
|
||
go func(desc string, g Worker) {
|
||
curErr := g()
|
||
if curErr != nil {
|
||
waitChan <- fmt.Errorf("run post worker %s return error:%v", desc, curErr)
|
||
}
|
||
}(worker.key.(string), worker.value.(Worker))
|
||
}
|
||
|
||
// 启动后的并行job
|
||
for _, j := range app.parallelJobs {
|
||
go j.value.(Job)()
|
||
}
|
||
|
||
xlog.Noticef("application[%v] run ok.", app.Name)
|
||
|
||
select {
|
||
case anyErr := <-waitChan:
|
||
xlog.Critif("scheduler stop with execute error:%v", anyErr)
|
||
return anyErr
|
||
}
|
||
}
|
||
|
||
func (app *Application) stop() {
|
||
for _, task := range app.stopTasks {
|
||
err := task.value.(Task)()
|
||
if err != nil {
|
||
xlog.Errorf("app stop, execute %v error:%v", task.key, err)
|
||
} else {
|
||
xlog.Infof("app %v stop, execute task:%v", app.Name, task.key)
|
||
}
|
||
}
|
||
//app.stopServices()
|
||
//app.stopServers()
|
||
}
|
||
|
||
//func (app *Application) stopServers() {
|
||
// for _, s := range app.servers {
|
||
// s.item.(*web.Engine).Stop()
|
||
// }
|
||
//}
|
||
|
||
//func (app *Application) stopServices() {
|
||
// for _, s := range app.services {
|
||
// s.item.(*joyservice.ServicesManager).Stop()
|
||
// }
|
||
//}
|