package boot import ( "errors" "fmt" "sync" "git.shuncheng.lu/bigthing/gocommon/pkg/cache/localcache" "git.shuncheng.lu/bigthing/gocommon/pkg/cache/redis" "git.shuncheng.lu/bigthing/gocommon/pkg/conf" "git.shuncheng.lu/bigthing/gocommon/pkg/database/db" "git.shuncheng.lu/bigthing/gocommon/pkg/database/elastic" "git.shuncheng.lu/bigthing/gocommon/pkg/database/multi_db" "git.shuncheng.lu/bigthing/gocommon/pkg/internal/util" "git.shuncheng.lu/bigthing/gocommon/pkg/logger" "git.shuncheng.lu/bigthing/gocommon/pkg/mq/kafka" "git.shuncheng.lu/bigthing/gocommon/pkg/mq/rocketmq" "git.shuncheng.lu/bigthing/gocommon/pkg/net/nacos" "git.shuncheng.lu/bigthing/gocommon/pkg/net/pprof" "git.shuncheng.lu/bigthing/gocommon/pkg/net/qconf" "git.shuncheng.lu/bigthing/gocommon/pkg/trace" ) // go get golang.org/x/tools/cmd/stringer //go:generate stringer -type=ResourceType type ResourceType uint8 type ConfigResource func(config *ResourceConfig) // 每变更一次类型都需要执行一次 go:generate const ( Config ResourceType = iota + 1 Logger Qconf DB MultiDB Redis Trace KafkaProducer KafkaConsumer LocalCache NacosDiscover // 发现中心 nacos NacosRegister // 注册中心 nacos Elastic Pprof RocketMQProducer RocketMQConsumer ) type Resource interface { Init() error Start() error Config() ResourceConfig } type initFunc func() error type startFunc func() error /** 注册init 函数 */ var ( resourceMap = map[ResourceType]Resource{ Config: newResource(conf.Init, nil), Logger: newResource(logger.Init, nil), DB: newResource(db.Init, nil), MultiDB: newResource(multi_db.Init, nil), Qconf: newResource(qconf.InitQconf, nil), Redis: newResource(redis.Init, nil), Trace: newResource(trace.Init, nil), KafkaProducer: newResource(kafka.InitProducer, nil), KafkaConsumer: newResource(kafka.InitConsumer, nil), LocalCache: newResource(localcache.Init, localcache.Start), Elastic: newResource(elastic.Init, nil), NacosDiscover: newResource(nacos.InitNacosDiscoverClient, nil), NacosRegister: newResource(nacos.InitNacosRegisterClientV2, nacos.StartNacosRegisterClientV2), Pprof: newResource(pprof.Init, nil), RocketMQProducer: newResource(rocketmq.InitProducer, nil), RocketMQConsumer: newResource(rocketmq.InitConsumer, rocketmq.StartConsumer), } // 锁,防止重复init initLock sync.Mutex initializedMap = map[ResourceType]Resource{} startedMap = map[ResourceType]Resource{} // 必须加载的资源 mustInitResource = []ResourceType{Config, Logger} ) // 允许多次init func Init(resource ...ResourceType) { if resource == nil || len(resource) == 0 { resource = mustInitResource // 这俩是必须初始化的 } // 排序和append_need_load_resource 加载资源的顺序 resource = sortResourceType(handlerResourceType(resource)) // initLock.Lock() defer initLock.Unlock() // 遍历初始化 for _, elem := range resource { resource, isExist := resourceMap[elem] // 存在 if isExist { // 是否已经启动过 if _, isInit := initializedMap[elem]; isInit { continue } util.Infof("[%s] start init...", elem) err := resource.Init() if err != nil { util.Painc(errors.New(fmt.Sprintf("init %s find err: %s", elem, err))) } initializedMap[elem] = resource util.Infof("[%s] end init...", elem) } } } func Start() { initLock.Lock() defer initLock.Unlock() for _type, elem := range initializedMap { if _, isStart := startedMap[_type]; isStart { continue } if err := elem.Start(); err != nil { util.Painc(err) } startedMap[_type] = elem } // 写进程pid util.WritePid() } func handlerResourceType(resource []ResourceType) []ResourceType { if resource == nil || len(resource) == 0 { return mustInitResource } resource = append(resource, mustInitResource...) filterMap := make(map[ResourceType]interface{}, 0) for _, elem := range resource { filterMap[elem] = nil } newResource := make([]ResourceType, 0) for key, _ := range filterMap { newResource = append(newResource, key) } return newResource }