xframe/vendor/github.com/polarismesh/polaris-go/pkg/plugin/manage.go

487 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Tencent is pleased to support the open source community by making polaris-go available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package plugin
import (
"fmt"
"reflect"
"sync/atomic"
"github.com/hashicorp/go-multierror"
"github.com/polarismesh/polaris-go/pkg/config"
"github.com/polarismesh/polaris-go/pkg/log"
"github.com/polarismesh/polaris-go/pkg/model"
"github.com/polarismesh/polaris-go/pkg/network"
"github.com/polarismesh/polaris-go/pkg/plugin/common"
)
var (
pluginIndex int32
// 插件的接口类型
pluginInterfaceTypes = make(map[common.Type]reflect.Type)
// 插件proxy类型
pluginProxyTypes = make(map[common.Type]reflect.Type)
// 全局插件类型列表,由各插件包注册进来
pluginTypes = make(map[common.Type]map[string]pluginType)
)
// pluginType 插件类型封装
type pluginType struct {
// 插件ID
pluginId int32
// 插件类型
reflectType reflect.Type
}
// IsPluginRegistered 检查插件是否已经注册
func IsPluginRegistered(typ common.Type, name string) bool {
var ok bool
var plugins map[string]pluginType
if plugins, ok = pluginTypes[typ]; !ok {
return false
}
if _, ok = plugins[name]; !ok {
return false
}
return true
}
// Supplier 插件提供者
type Supplier interface {
// GetPlugin 获取插件实例
GetPlugin(typ common.Type, name string) (Plugin, error)
// GetPluginById 通过id获取插件实例
GetPluginById(id int32) (Plugin, error)
// GetPluginsByType 获取一个类型的加载了的插件名字
GetPluginsByType(typ common.Type) []string
// GetEventSubscribers 获取插件事件监听器
GetEventSubscribers(event common.PluginEventType) []common.PluginEventHandler
// RegisterEventSubscriber 注册插件事件监听器必须在Plugin.Init方法中进行否则会出现并发读写问题
RegisterEventSubscriber(event common.PluginEventType, handler common.PluginEventHandler)
}
// Manager 插件管理器统一接口
type Manager interface {
Supplier
// InitPlugins 初始化插件列表
InitPlugins(initContext InitContext, types []common.Type, engine model.Engine, delegate func() error) (err error)
// DestroyPlugins 销毁已初始化的插件列表
DestroyPlugins() (err error)
// StartPlugins 执行已经初始化完毕的插件
StartPlugins() error
}
// pluginWrapper 插件实例包装类
type pluginWrapper struct {
// 插件唯一标识,与具体插件类型对应
id int32
// 具体插件标识
instance Plugin
}
// NewPluginManager 创建插件管理器实例
func NewPluginManager() Manager {
return &manager{
plugins: make(map[common.Type]map[string]*pluginWrapper),
eventSubscriber: make(map[common.PluginEventType][]common.PluginEventHandler),
idToPlugins: make(map[int32]Plugin),
}
}
// Manager 插件管理器
type manager struct {
plugins map[common.Type]map[string]*pluginWrapper
idToPlugins map[int32]Plugin
eventSubscriber map[common.PluginEventType][]common.PluginEventHandler
// 是否已经初始化,初始化后不允许修改任何数据结构
initialized uint32
}
// instanceOf 判断是否实现了对应的接口
func instanceOf(value interface{}, interfaceType reflect.Type) bool {
return reflect.PtrTo(reflect.TypeOf(value).Elem()).Implements(interfaceType)
}
// checkInterfaceType 检查插件是否实现了对应的插件接口
func checkInterfaceType(plugin Plugin) error {
intfType := pluginInterfaceTypes[plugin.Type()]
if !instanceOf(plugin, intfType) {
return model.NewSDKError(model.ErrCodePluginError, nil,
"plugin %s for type %s must implement %s interface", plugin.Name(), plugin.Type(), intfType)
}
return nil
}
// RegisterPluginInterface 注册插件接口类型
func RegisterPluginInterface(typ common.Type, plugin interface{}) {
if _, ok := pluginInterfaceTypes[typ]; ok {
// 开发态错误直接panic以便快速发现问题
panic(fmt.Sprintf("duplicate register for plugin type %s", typ))
}
pluginInterfaceTypes[typ] = reflect.TypeOf(plugin).Elem()
}
// RegisterPluginProxy 注册插件proxy类型
func RegisterPluginProxy(typ common.Type, proxy PluginProxy) {
if _, ok := pluginProxyTypes[typ]; ok {
panic(fmt.Sprintf("duplicate register for plugin proxy type %s", typ))
}
pluginProxyTypes[typ] = reflect.TypeOf(proxy).Elem()
}
// RegisterPlugin 注册插件到全局配置对象,插件名重复则返回错误
func RegisterPlugin(plugin Plugin) {
RegisterConfigurablePlugin(plugin, nil)
}
// RegisterConfigurablePlugin 注册插件到全局配置对象,并注册插件配置类型
func RegisterConfigurablePlugin(plugin Plugin, cfg config.BaseConfig) {
if err := checkInterfaceType(plugin); err != nil {
// 插件注册失败则直接panic让用户直接感知
panic(err)
}
name := plugin.Name()
typ := plugin.Type()
plugs, exists := pluginTypes[typ]
if !exists {
plugs = make(map[string]pluginType)
pluginTypes[typ] = plugs
}
pluginIdx := atomic.AddInt32(&pluginIndex, 1)
plugs[name] = pluginType{
pluginId: pluginIdx,
reflectType: reflect.TypeOf(plugin).Elem(),
}
config.RegisterPluginConfigType(typ, name, cfg)
}
// createPlugin 反射创建插件
func createPlugin(typ reflect.Type) Plugin {
value := reflect.New(typ).Interface()
return value.(Plugin)
}
// createPluginProxy 创建插件proxy
func createPluginProxy(typ common.Type) PluginProxy {
t := pluginProxyTypes[typ]
value := reflect.New(t).Interface()
return value.(PluginProxy)
}
// InitPlugins 初始化所有已注册插件
func (m *manager) InitPlugins(
ctx InitContext, types []common.Type, engine model.Engine, delegateInit func() error) (err error) {
if atomic.LoadUint32(&m.initialized) > 0 {
return model.NewSDKError(model.ErrCodeInvalidStateError, nil, "manager has been initialized")
}
pluginSlice := make([]*pluginWrapper, 0, len(types)*2)
for _, typ := range types {
plugs, ok := pluginTypes[typ]
if !ok {
err := model.NewSDKError(model.ErrCodePluginError, nil,
"InitPlugins: invalid plugin type %v", typ)
fmt.Printf("%+v %+v %+v", types, pluginTypes, err)
return m.cleanupWhenError(err)
}
plugInstances, ok := m.plugins[typ]
if !ok {
plugInstances = make(map[string]*pluginWrapper, 0)
m.plugins[typ] = plugInstances
}
for _, plugClazz := range plugs {
plug := createPlugin(plugClazz.reflectType)
// if !pluginNames.Contains(plug.Name()) {
// continue
// }
proxy := createPluginProxy(typ)
proxy.SetRealPlugin(plug, engine)
if !plug.IsEnable(ctx.Config) {
continue
}
wrapper := &pluginWrapper{
id: plugClazz.pluginId,
instance: proxy,
}
plugInstances[proxy.Name()] = wrapper
pluginSlice = append(pluginSlice, wrapper)
}
}
// 初始化必须保持有序
for _, plug := range pluginSlice {
ctx.PluginIndex = plug.id
err = plug.instance.Init(&ctx)
if err != nil {
return m.cleanupWhenError(model.NewSDKError(model.ErrCodePluginError, err,
"InitPlugins: fail to init plugin name %v:%s", plug.instance.Type(), plug.instance.Name()))
}
m.idToPlugins[plug.id] = plug.instance
log.GetBaseLogger().Infof(
"Initialized plugin type %v, name %s, id %d",
plug.instance.Type(), plug.instance.Name(), ctx.PluginIndex)
}
if err = delegateInit(); err != nil {
return m.cleanupWhenError(model.NewSDKError(model.ErrCodePluginError, err,
"InitPlugins: fail to init delegate"))
}
atomic.StoreUint32(&m.initialized, 1)
return nil
}
// StartPlugins 启动所有插件
func (m *manager) StartPlugins() error {
if atomic.LoadUint32(&m.initialized) == 0 {
return model.NewSDKError(model.ErrCodeInvalidStateError, nil, "manager has not been initialized")
}
var err error
startedPlugins := model.HashSet{}
for id, plug := range m.idToPlugins {
startedPlugins.Add(id)
if err = plug.Start(); err != nil {
log.GetBaseLogger().Errorf("fail to start plugin %s, err is %v", plug.Name(), err)
break
}
}
if err != nil && len(startedPlugins) > 0 {
// 回滚所有插件
for idValue := range startedPlugins {
_ = m.idToPlugins[idValue.(int32)].Destroy()
}
}
return err
}
// cleanupWhenError 清理插件初始化结果,并返回输入错误
func (m *manager) cleanupWhenError(sdkErr model.SDKError) error {
if nil == sdkErr {
return nil
}
if len(m.plugins) == 0 {
return sdkErr
}
for typ, plugInstances := range m.plugins {
if len(plugInstances) == 0 {
continue
}
for name, plugInst := range plugInstances {
if err := plugInst.instance.Destroy(); err != nil {
log.GetBaseLogger().Errorf("fail to destroy plugin %v:%s, err %v", typ, name, err)
}
}
}
return sdkErr
}
// DestroyPlugins 销毁已初始化的插件列表
func (m *manager) DestroyPlugins() (errs error) {
var err error
for typ, plugs := range m.plugins {
for name, plug := range plugs {
err = plug.instance.Destroy()
if err != nil {
errs = multierror.Append(errs, multierror.Prefix(err,
fmt.Sprintf("DestroyPlugins: plugin %v:%s error, ", typ, name)))
}
}
}
if errs != nil {
return model.NewSDKError(model.ErrCodePluginError, errs, "DestroyPlugins: plugins destroy errors")
}
return nil
}
// GetPlugin 获取插件
func (m *manager) GetPlugin(typ common.Type, name string) (Plugin, error) {
plugins, exists := m.plugins[typ]
if !exists {
return nil, model.NewSDKError(model.ErrCodePluginError, nil,
"GetPlugin: invalid plugin type %v", typ)
}
plug, exists := plugins[name]
if !exists {
return nil, model.NewSDKError(model.ErrCodeAPIInvalidConfig, nil,
"GetPlugin: plugin name %s not registered", name)
}
return plug.instance, nil
}
// GetPluginsByType 获取一个类型的加载的插件名字
func (m *manager) GetPluginsByType(typ common.Type) []string {
var res []string
plugins, exists := m.plugins[typ]
if !exists {
return res
}
for k := range plugins {
res = append(res, k)
}
return res
}
// GetPluginById 通过id获取插件
func (m *manager) GetPluginById(id int32) (Plugin, error) {
plugin, exists := m.idToPlugins[id]
if !exists {
return nil, model.NewSDKError(model.ErrCodePluginError, nil, "GetPluginById: not registered plugin id %d", id)
}
return plugin, nil
}
// GetPluginId 获取插件
func GetPluginId(typ common.Type, name string) (int32, error) {
plugs, exists := pluginTypes[typ]
if !exists {
return 0, model.NewSDKError(model.ErrCodePluginError, nil,
"GetPlugin: invalid plugin type %v", typ)
}
plug, exists := plugs[name]
if !exists {
return 0, model.NewSDKError(model.ErrCodeAPIInvalidConfig, nil,
"GetPlugin: plugin name %s not registered", name)
}
return plug.pluginId, nil
}
// GetPluginCount 获取某个类型下注册的插件数量
func GetPluginCount(typ common.Type) int {
plugs := pluginTypes[typ]
return len(plugs)
}
// RegisterEventSubscriber 注册事件回调函数
func (m *manager) RegisterEventSubscriber(event common.PluginEventType, handler common.PluginEventHandler) {
if atomic.LoadUint32(&m.initialized) > 0 {
panic("manager has initialized")
}
if handlers, ok := m.eventSubscriber[event]; ok {
handlers = append(handlers, handler)
m.eventSubscriber[event] = handlers
return
}
handlers := make([]common.PluginEventHandler, 0)
handlers = append(handlers, handler)
m.eventSubscriber[event] = handlers
}
// GetEventSubscribers 注册事件回调函数
func (m *manager) GetEventSubscribers(event common.PluginEventType) []common.PluginEventHandler {
if atomic.LoadUint32(&m.initialized) == 0 {
panic("manager has not initialized")
}
return m.eventSubscriber[event]
}
// InitContext 用于插件初始化的上下文对象
type InitContext struct {
Config config.Configuration
Plugins Supplier
ValueCtx model.ValueContext
ConnManager network.ConnectionManager
PluginIndex int32
SDKContextID string
}
// //插件ID
// type IdAwarePlugin interface {
// Plugin
// //插件标识
// ID() int32
// }
// Plugin 所有插件的基础接口
type Plugin interface {
// Type 插件类型
Type() common.Type
// ID 插件id
ID() int32
// GetSDKContextID 返回插件所属的sdkContext的uuid
GetSDKContextID() string
// Name 插件名,一个类型下插件名唯一
Name() string
// Init 初始化插件
Init(ctx *InitContext) error
// Start 启动插件对于需要依赖外部资源以及启动协程的操作在Start方法里面做
Start() error
// Destroy 销毁插件,可用于释放资源
Destroy() error
// IsEnable 插件是否启用
IsEnable(cfg config.Configuration) bool
}
// PluginBase Plugin Base
type PluginBase struct {
pluginIndex int32
sdkID string
}
// Type 插件类型
func (b *PluginBase) Type() common.Type {
return common.TypePluginBase
}
// Name 返回插件名
func (b *PluginBase) Name() string {
return common.TypePluginBase.String()
}
// Init init
func (b *PluginBase) Init(ctx *InitContext) error {
b.pluginIndex = ctx.PluginIndex
b.sdkID = ctx.SDKContextID
return nil
}
// ID 插件id
func (b *PluginBase) ID() int32 {
return b.pluginIndex
}
// GetSDKContextID 获取所属sdkContext的uuid
func (b *PluginBase) GetSDKContextID() string {
return b.sdkID
}
// Destroy 销毁插件
func (b *PluginBase) Destroy() error {
return nil
}
// Start 启动插件
func (b *PluginBase) Start() error {
// do nothing
return nil
}
// NewPluginBase 创建pluginbase
func NewPluginBase(ctx *InitContext) *PluginBase {
res := &PluginBase{}
_ = res.Init(ctx)
return res
}
// PluginProxy Plugin的代理
type PluginProxy interface {
Plugin
SetRealPlugin(plugin Plugin, engine model.Engine)
}
// IsEnable is enable
func (b *PluginBase) IsEnable(cfg config.Configuration) bool {
return true
}