mirror of
				https://gitee.com/dromara/mayfly-go
				synced 2025-11-04 08:20:25 +08:00 
			
		
		
		
	
		
			
	
	
		
			285 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			285 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package application
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								import (
							 | 
						|||
| 
								 | 
							
									"context"
							 | 
						|||
| 
								 | 
							
									"fmt"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/internal/es/application/dto"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/internal/es/domain/entity"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/internal/es/domain/repository"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/internal/es/esm/esi"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/internal/es/imsg"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/internal/pkg/consts"
							 | 
						|||
| 
								 | 
							
									tagapp "mayfly-go/internal/tag/application"
							 | 
						|||
| 
								 | 
							
									tagdto "mayfly-go/internal/tag/application/dto"
							 | 
						|||
| 
								 | 
							
									tagentity "mayfly-go/internal/tag/domain/entity"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/pkg/base"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/pkg/errorx"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/pkg/model"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/pkg/pool"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/pkg/utils/collx"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/pkg/utils/stringx"
							 | 
						|||
| 
								 | 
							
									"mayfly-go/pkg/utils/structx"
							 | 
						|||
| 
								 | 
							
									"time"
							 | 
						|||
| 
								 | 
							
								)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								type Instance interface {
							 | 
						|||
| 
								 | 
							
									base.App[*entity.EsInstance]
							 | 
						|||
| 
								 | 
							
									// GetPageList 分页获取数据库实例
							 | 
						|||
| 
								 | 
							
									GetPageList(condition *entity.InstanceQuery, orderBy ...string) (*model.PageResult[*entity.EsInstance], error)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// DoConn 获取连接并执行函数
							 | 
						|||
| 
								 | 
							
									DoConn(instanceId uint64, fn func(*esi.EsConn) error) error
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									TestConn(instance *entity.EsInstance, ac *tagentity.ResourceAuthCert) (map[string]any, error)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									SaveInst(ctx context.Context, d *dto.SaveEsInstance) (uint64, error)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									Delete(ctx context.Context, instanceId uint64) error
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								var _ Instance = &instanceAppImpl{}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								var connPool = make(map[uint64]pool.Pool)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								type instanceAppImpl struct {
							 | 
						|||
| 
								 | 
							
									base.AppImpl[*entity.EsInstance, repository.EsInstance]
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									tagApp              tagapp.TagTree          `inject:"T"`
							 | 
						|||
| 
								 | 
							
									resourceAuthCertApp tagapp.ResourceAuthCert `inject:"T"`
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								// GetPageList 分页获取数据库实例
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) GetPageList(condition *entity.InstanceQuery, orderBy ...string) (*model.PageResult[*entity.EsInstance], error) {
							 | 
						|||
| 
								 | 
							
									return app.GetRepo().GetInstanceList(condition, orderBy...)
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) DoConn(instanceId uint64, fn func(*esi.EsConn) error) error {
							 | 
						|||
| 
								 | 
							
									// 通过实例id获取实例连接信息
							 | 
						|||
| 
								 | 
							
									p, err := app.getPool(instanceId)
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									// 从连接池中获取一个可用的连接
							 | 
						|||
| 
								 | 
							
									c, err := p.Get()
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									ec := c.(*esi.EsConn)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// 用完后放回连接池
							 | 
						|||
| 
								 | 
							
									defer p.Put(c)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									return fn(ec)
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) getPool(instanceId uint64) (pool.Pool, error) {
							 | 
						|||
| 
								 | 
							
									// 获取连接池,如果没有,则创建一个
							 | 
						|||
| 
								 | 
							
									if p, ok := connPool[instanceId]; !ok {
							 | 
						|||
| 
								 | 
							
										var err error
							 | 
						|||
| 
								 | 
							
										p, err = pool.NewChannelPool(&pool.Config{
							 | 
						|||
| 
								 | 
							
											InitialCap:  1,                //资源池初始连接数
							 | 
						|||
| 
								 | 
							
											MaxCap:      10,               //最大空闲连接数
							 | 
						|||
| 
								 | 
							
											MaxIdle:     10,               //最大并发连接数
							 | 
						|||
| 
								 | 
							
											IdleTimeout: 10 * time.Minute, // 连接最大空闲时间,过期则失效
							 | 
						|||
| 
								 | 
							
											Factory: func() (interface{}, error) {
							 | 
						|||
| 
								 | 
							
												return app.createConn(instanceId)
							 | 
						|||
| 
								 | 
							
											},
							 | 
						|||
| 
								 | 
							
											Close: func(v interface{}) error {
							 | 
						|||
| 
								 | 
							
												return v.(*esi.EsConn).Close()
							 | 
						|||
| 
								 | 
							
											},
							 | 
						|||
| 
								 | 
							
											Ping: func(v interface{}) error {
							 | 
						|||
| 
								 | 
							
												return v.(*esi.EsConn).Ping()
							 | 
						|||
| 
								 | 
							
											},
							 | 
						|||
| 
								 | 
							
										})
							 | 
						|||
| 
								 | 
							
										if err != nil {
							 | 
						|||
| 
								 | 
							
											return nil, err
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										connPool[instanceId] = p
							 | 
						|||
| 
								 | 
							
										return p, nil
							 | 
						|||
| 
								 | 
							
									} else {
							 | 
						|||
| 
								 | 
							
										return p, nil
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) createConn(instanceId uint64) (*esi.EsConn, error) {
							 | 
						|||
| 
								 | 
							
									// 缓存不存在,则重新连接
							 | 
						|||
| 
								 | 
							
									instance, err := app.GetById(instanceId)
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return nil, errorx.NewBiz("es instance not found")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									ei, err := app.ToEsInfo(instance, nil)
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return nil, err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									ei.CodePath = app.tagApp.ListTagPathByTypeAndCode(int8(tagentity.TagTypeEsInstance), instance.Code)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									conn, _, err := ei.Conn()
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return nil, err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									// 缓存连接信息
							 | 
						|||
| 
								 | 
							
									return conn, nil
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) ToEsInfo(instance *entity.EsInstance, ac *tagentity.ResourceAuthCert) (*esi.EsInfo, error) {
							 | 
						|||
| 
								 | 
							
									ei := new(esi.EsInfo)
							 | 
						|||
| 
								 | 
							
									ei.InstanceId = instance.Id
							 | 
						|||
| 
								 | 
							
									structx.Copy(ei, instance)
							 | 
						|||
| 
								 | 
							
									ei.OriginUrl = fmt.Sprintf("http://%s:%d", instance.Host, instance.Port)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									if ac != nil {
							 | 
						|||
| 
								 | 
							
										if ac.Ciphertext == "" && ac.Name != "" {
							 | 
						|||
| 
								 | 
							
											ac1, err := app.resourceAuthCertApp.GetAuthCert(ac.Name)
							 | 
						|||
| 
								 | 
							
											if err == nil {
							 | 
						|||
| 
								 | 
							
												ac = ac1
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									} else {
							 | 
						|||
| 
								 | 
							
										if instance.Code != "" {
							 | 
						|||
| 
								 | 
							
											ac2, err := app.resourceAuthCertApp.GetResourceAuthCert(tagentity.TagTypeEsInstance, instance.Code)
							 | 
						|||
| 
								 | 
							
											if err == nil {
							 | 
						|||
| 
								 | 
							
												ac = ac2
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									if ac != nil && ac.Ciphertext != "" {
							 | 
						|||
| 
								 | 
							
										ei.Username = ac.Username
							 | 
						|||
| 
								 | 
							
										ei.Password = ac.Ciphertext
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									return ei, nil
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) TestConn(instance *entity.EsInstance, ac *tagentity.ResourceAuthCert) (map[string]any, error) {
							 | 
						|||
| 
								 | 
							
									instance.Network = instance.GetNetwork()
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									ei, err := app.ToEsInfo(instance, ac)
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return nil, err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									_, res, err := ei.Conn()
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return nil, err
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
									return res, nil
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) SaveInst(ctx context.Context, instance *dto.SaveEsInstance) (uint64, error) {
							 | 
						|||
| 
								 | 
							
									instanceEntity := instance.EsInstance
							 | 
						|||
| 
								 | 
							
									// 默认tcp连接
							 | 
						|||
| 
								 | 
							
									instanceEntity.Network = instanceEntity.GetNetwork()
							 | 
						|||
| 
								 | 
							
									resourceType := consts.ResourceTypeEsInstance
							 | 
						|||
| 
								 | 
							
									authCerts := instance.AuthCerts
							 | 
						|||
| 
								 | 
							
									tagCodePaths := instance.TagCodePaths
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// 查找是否存在该库
							 | 
						|||
| 
								 | 
							
									oldInstance := &entity.EsInstance{
							 | 
						|||
| 
								 | 
							
										Host:               instanceEntity.Host,
							 | 
						|||
| 
								 | 
							
										Port:               instanceEntity.Port,
							 | 
						|||
| 
								 | 
							
										SshTunnelMachineId: instanceEntity.SshTunnelMachineId,
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									err := app.GetByCond(oldInstance)
							 | 
						|||
| 
								 | 
							
									if instanceEntity.Id == 0 {
							 | 
						|||
| 
								 | 
							
										if err == nil {
							 | 
						|||
| 
								 | 
							
											return 0, errorx.NewBizI(ctx, imsg.ErrEsInstExist)
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										instanceEntity.Code = stringx.Rand(10)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
										return instanceEntity.Id, app.Tx(ctx, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
											return app.Insert(ctx, instanceEntity)
							 | 
						|||
| 
								 | 
							
										}, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
											return app.resourceAuthCertApp.RelateAuthCert(ctx, &tagdto.RelateAuthCert{
							 | 
						|||
| 
								 | 
							
												ResourceCode: instanceEntity.Code,
							 | 
						|||
| 
								 | 
							
												ResourceType: tagentity.TagType(resourceType),
							 | 
						|||
| 
								 | 
							
												AuthCerts:    authCerts,
							 | 
						|||
| 
								 | 
							
											})
							 | 
						|||
| 
								 | 
							
										}, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
											return app.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
							 | 
						|||
| 
								 | 
							
												ResourceTag:        app.genEsInstanceResourceTag(instanceEntity, authCerts),
							 | 
						|||
| 
								 | 
							
												ParentTagCodePaths: tagCodePaths,
							 | 
						|||
| 
								 | 
							
											})
							 | 
						|||
| 
								 | 
							
										})
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// 如果存在该库,则校验修改的库是否为该库
							 | 
						|||
| 
								 | 
							
									if err == nil {
							 | 
						|||
| 
								 | 
							
										if oldInstance.Id != instanceEntity.Id {
							 | 
						|||
| 
								 | 
							
											return 0, errorx.NewBizI(ctx, imsg.ErrEsInstExist)
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									} else {
							 | 
						|||
| 
								 | 
							
										// 根据host等未查到旧数据,则需要根据id重新获取,因为后续需要使用到code
							 | 
						|||
| 
								 | 
							
										oldInstance, err = app.GetById(instanceEntity.Id)
							 | 
						|||
| 
								 | 
							
										if err != nil {
							 | 
						|||
| 
								 | 
							
											return 0, errorx.NewBiz("db instance not found")
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									return oldInstance.Id, app.Tx(ctx, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
										return app.UpdateById(ctx, instanceEntity)
							 | 
						|||
| 
								 | 
							
									}, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
										return app.resourceAuthCertApp.RelateAuthCert(ctx, &tagdto.RelateAuthCert{
							 | 
						|||
| 
								 | 
							
											ResourceCode: oldInstance.Code,
							 | 
						|||
| 
								 | 
							
											ResourceType: tagentity.TagType(resourceType),
							 | 
						|||
| 
								 | 
							
											AuthCerts:    authCerts,
							 | 
						|||
| 
								 | 
							
										})
							 | 
						|||
| 
								 | 
							
									}, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
										if instanceEntity.Name != oldInstance.Name {
							 | 
						|||
| 
								 | 
							
											if err := app.tagApp.UpdateTagName(ctx, tagentity.TagTypeDbInstance, oldInstance.Code, instanceEntity.Name); err != nil {
							 | 
						|||
| 
								 | 
							
												return err
							 | 
						|||
| 
								 | 
							
											}
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
										return app.tagApp.SaveResourceTag(ctx, &tagdto.SaveResourceTag{
							 | 
						|||
| 
								 | 
							
											ResourceTag:        app.genEsInstanceResourceTag(oldInstance, authCerts),
							 | 
						|||
| 
								 | 
							
											ParentTagCodePaths: tagCodePaths,
							 | 
						|||
| 
								 | 
							
										})
							 | 
						|||
| 
								 | 
							
									})
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) genEsInstanceResourceTag(ei *entity.EsInstance, authCerts []*tagentity.ResourceAuthCert) *tagdto.ResourceTag {
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// 授权证书对应的tag
							 | 
						|||
| 
								 | 
							
									authCertTags := collx.ArrayMap[*tagentity.ResourceAuthCert, *tagdto.ResourceTag](authCerts, func(val *tagentity.ResourceAuthCert) *tagdto.ResourceTag {
							 | 
						|||
| 
								 | 
							
										return &tagdto.ResourceTag{
							 | 
						|||
| 
								 | 
							
											Code: val.Name,
							 | 
						|||
| 
								 | 
							
											Name: val.Username,
							 | 
						|||
| 
								 | 
							
											Type: tagentity.TagTypeAuthCert,
							 | 
						|||
| 
								 | 
							
										}
							 | 
						|||
| 
								 | 
							
									})
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									// es实例
							 | 
						|||
| 
								 | 
							
									return &tagdto.ResourceTag{
							 | 
						|||
| 
								 | 
							
										Code:     ei.Code,
							 | 
						|||
| 
								 | 
							
										Name:     ei.Name,
							 | 
						|||
| 
								 | 
							
										Type:     tagentity.TagTypeEsInstance,
							 | 
						|||
| 
								 | 
							
										Children: authCertTags,
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								func (app *instanceAppImpl) Delete(ctx context.Context, instanceId uint64) error {
							 | 
						|||
| 
								 | 
							
									instance, err := app.GetById(instanceId)
							 | 
						|||
| 
								 | 
							
									if err != nil {
							 | 
						|||
| 
								 | 
							
										return errorx.NewBiz("db instnace not found")
							 | 
						|||
| 
								 | 
							
									}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
									return app.Tx(ctx, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
										// 删除该实例
							 | 
						|||
| 
								 | 
							
										return app.DeleteById(ctx, instanceId)
							 | 
						|||
| 
								 | 
							
									}, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
										// 删除该实例关联的授权凭证信息
							 | 
						|||
| 
								 | 
							
										return app.resourceAuthCertApp.RelateAuthCert(ctx, &tagdto.RelateAuthCert{
							 | 
						|||
| 
								 | 
							
											ResourceCode: instance.Code,
							 | 
						|||
| 
								 | 
							
											ResourceType: tagentity.TagType(consts.ResourceTypeEsInstance),
							 | 
						|||
| 
								 | 
							
										})
							 | 
						|||
| 
								 | 
							
									}, func(ctx context.Context) error {
							 | 
						|||
| 
								 | 
							
										// 删除该实例关联的tag信息
							 | 
						|||
| 
								 | 
							
										return app.tagApp.DeleteTagByParam(ctx, &tagdto.DelResourceTag{
							 | 
						|||
| 
								 | 
							
											ResourceCode: instance.Code,
							 | 
						|||
| 
								 | 
							
											ResourceType: tagentity.TagType(consts.ResourceTypeEsInstance),
							 | 
						|||
| 
								 | 
							
										})
							 | 
						|||
| 
								 | 
							
									})
							 | 
						|||
| 
								 | 
							
								}
							 |