5. 数据访问层

5.1 仓储接口定义

插件仓储接口

文件位置:backend/domain/plugin/repository/plugin.go

type PluginRepository interface {// DeleteDraftPlugin 删除插件草稿DeleteDraftPlugin(ctx context.Context, pluginID int64) error// DeleteAPPAllPlugins 删除应用下所有插件DeleteAPPAllPlugins(ctx context.Context, appID int64) (pluginIDs []int64, err error)// GetDraftPlugin 获取插件草稿GetDraftPlugin(ctx context.Context, pluginID int64, opt *dal.PluginSelectedOption) (*entity.PluginInfo, error)// 其他CRUD方法...
}

删除方法特点

  • 事务删除:DeleteDraftPlugin方法支持事务操作,确保数据一致性
  • 批量删除:DeleteAPPAllPlugins支持批量删除应用下的所有插件
  • 上下文支持:支持context.Context进行请求链路追踪
  • 错误处理:返回error类型,便于上层进行错误处理
  • ID定位:通过唯一pluginID精确定位要删除的插件资源

5.2 数据访问对象(DAO)

插件删除的具体实现

文件位置:backend/domain/plugin/repository/plugin_impl.go

插件删除操作涉及多个数据表的级联删除,需要通过事务确保数据一致性:

func (p *pluginRepoImpl) DeleteDraftPlugin(ctx context.Context, pluginID int64) (err error) {tx := p.query.Begin()if tx.Error != nil {return tx.Error}defer func() {if r := recover(); r != nil {if e := tx.Rollback(); e != nil {logs.CtxErrorf(ctx, "rollback failed, err=%v", e)}err = fmt.Errorf("catch panic: %v\nstack=%s", r, string(debug.Stack()))return}if err != nil {if e := tx.Rollback(); e != nil {logs.CtxErrorf(ctx, "rollback failed, err=%v", e)}}}()// 删除插件草稿数据err = p.pluginDraftDAO.DeleteWithTX(ctx, tx, pluginID)if err != nil {return err}// 删除插件基础数据err = p.pluginDAO.DeleteWithTX(ctx, tx, pluginID)if err != nil {return err}// 删除插件版本数据err = p.pluginVersionDAO.DeleteWithTX(ctx, tx, pluginID)if err != nil {return err}// 删除插件下的所有工具草稿err = p.toolDraftDAO.DeleteAllWithTX(ctx, tx, pluginID)if err != nil {return err}// 删除插件下的所有工具数据err = p.toolDAO.DeleteAllWithTX(ctx, tx, pluginID)if err != nil {return err}// 删除工具版本数据err = p.toolVersionDAO.DeleteWithTX(ctx, tx, pluginID)if err != nil {return err}return tx.Commit()
}

删除操作的关键特点

  1. 事务保证:使用数据库事务确保所有删除操作的原子性
  2. 级联删除:删除插件时同时删除相关的工具、版本等数据
  3. 异常处理:完善的panic恢复和事务回滚机制
  4. 数据完整性:确保删除操作不会留下孤立的数据记录
  5. 多表协调:协调删除插件相关的多个数据表

删除涉及的数据表

  • plugin_draft:插件草稿表
  • plugin:插件基础信息表
  • plugin_version:插件版本表
  • tool_draft:工具草稿表
  • tool:工具信息表
  • tool_version:工具版本表
PluginDraftDAO结构体

文件位置:backend/domain/plugin/internal/dal/plugin_draft.go

PluginDraftDAO是插件草稿数据访问的具体实现,负责与数据库进行交互,处理插件草稿资源的持久化操作。

package dalimport ("context""encoding/json""fmt""gorm.io/gen""gorm.io/gorm""github.com/coze-dev/coze-studio/backend/domain/plugin/entity""github.com/coze-dev/coze-studio/backend/domain/plugin/internal/dal/model""github.com/coze-dev/coze-studio/backend/domain/plugin/internal/dal/query""github.com/coze-dev/coze-studio/backend/infra/contract/idgen""github.com/coze-dev/coze-studio/backend/pkg/slices"
)type PluginDraftDAO struct {query *query.QueryidGen idgen.IDGenerator
}func NewPluginDraftDAO(db *gorm.DB, generator idgen.IDGenerator) *PluginDraftDAO {return &PluginDraftDAO{query: query.Use(db),idGen: generator,}
}
插件删除操作实现

删除插件草稿

func (p *PluginDraftDAO) DeleteWithTX(ctx context.Context, tx *query.QueryTx, pluginID int64) (err error) {table := tx.PluginDraft_, err = table.WithContext(ctx).Where(table.ID.Eq(pluginID)).Delete()if err != nil {return err}return nil
}
ToolDraftDAO删除操作

文件位置:backend/domain/plugin/internal/dal/tool_draft.go

批量删除工具草稿

func (t *ToolDraftDAO) DeleteAllWithTX(ctx context.Context, tx *query.QueryTx, pluginID int64) (err error) {const limit = 20table := tx.ToolDraftfor {info, err := table.WithContext(ctx).Where(table.PluginID.Eq(pluginID)).Limit(limit).Delete()if err != nil {return err}if info.RowsAffected < limit {break}}return nil
}
数据转换方法

DO到PO转换(Domain Object to Persistent Object)

func (p *PluginDraftDAO) pluginInfoDO2PO(plugin *entity.PluginInfo) *model.PluginDraft {mf, _ := plugin.Manifest.EncryptAuthPayload()return &model.PluginDraft{ID:          plugin.ID,SpaceID:     plugin.SpaceID,DeveloperID: plugin.DeveloperID,PluginType:  int32(plugin.PluginType),IconURI:     plugin.GetIconURI(),ServerURL:   plugin.GetServerURL(),AppID:       plugin.GetAPPID(),Manifest:    mf,OpenapiDoc:  plugin.OpenapiDoc,}
}

PO到DO转换(Persistent Object to Domain Object)

type pluginDraftPO model.PluginDraftfunc (p pluginDraftPO) ToDO() *entity.PluginInfo {plugin := &entity.PluginInfo{ID:          p.ID,SpaceID:     p.SpaceID,DeveloperID: p.DeveloperID,PluginType:  common.PluginType(p.PluginType),IconURI:     &p.IconURI,ServerURL:   &p.ServerURL,APPID:       &p.AppID,Manifest:    p.Manifest,OpenapiDoc:  p.OpenapiDoc,CreatedAt:   p.CreatedAt,UpdatedAt:   p.UpdatedAt,}return plugin
}

删除操作特点

  1. 事务删除:DeleteWithTX方法支持事务操作,确保数据一致性
  2. 精确定位:通过pluginID精确定位要删除的插件资源
  3. 条件构建:使用GORM Gen生成的类型安全查询条件
  4. 物理删除:执行物理删除操作,从数据库中彻底移除记录
  5. 批量删除:ToolDraftDAO支持批量删除插件下的所有工具
  6. 分页删除:使用limit分页删除,避免大量数据删除时的性能问题

删除插件的完整数据访问流程

在删除插件的场景中,数据访问层的操作流程如下:

  1. 删除前验证:调用GetDraftPlugin方法获取插件信息,验证资源存在性
  2. 权限检查:在应用层验证当前用户是否为插件开发者
  3. 事务开始:开启数据库事务,确保删除操作的原子性
  4. 级联删除:依次删除插件草稿、插件基础数据、版本数据、工具数据等
  5. 事务提交:所有删除操作成功后提交事务
  6. 错误回滚:任何删除操作失败时回滚事务,保证数据一致性

这种设计确保了删除操作的安全性、可靠性和数据完整性。

数据访问层删除操作总结

删除插件在数据访问层的实现具有以下特点:

  1. 事务保证:所有删除操作在事务中执行,确保数据一致性
  2. 级联删除:自动删除插件相关的所有数据,包括工具、版本等
  3. 类型安全:使用GORM Gen生成的类型安全查询条件,避免SQL注入风险
  4. 错误处理:完善的错误处理和事务回滚机制
  5. 物理删除:执行真正的物理删除操作,彻底从数据库中移除记录
  6. 性能优化:通过分页删除和精确的WHERE条件,确保删除操作的高效执行

5.3 插件数据模型

PluginDraft数据模型

文件位置:backend/domain/plugin/internal/dal/model/plugin_draft.gen.go

该文件由GORM代码生成工具自动生成,定义了与数据库表对应的Go结构体。在删除插件操作中,该模型定义了数据库记录的结构,为删除操作提供了数据映射基础。

// Code generated by gorm.io/gen. DO NOT EDIT.
package modelconst TableNamePluginDraft = "plugin_draft"// PluginDraft plugin_draft
type PluginDraft struct {ID          int64                `gorm:"column:id;primaryKey;autoIncrement:true;comment:id" json:"id"`                                          // idSpaceID     int64                `gorm:"column:space_id;not null;comment:space id" json:"space_id"`                                             // space idDeveloperID int64                `gorm:"column:developer_id;not null;comment:developer id" json:"developer_id"`                                 // developer idPluginType  int32                `gorm:"column:plugin_type;not null;comment:plugin type" json:"plugin_type"`                                   // plugin typeIconURI     string               `gorm:"column:icon_uri;comment:icon uri" json:"icon_uri"`                                                      // icon uriServerURL   string               `gorm:"column:server_url;comment:server url" json:"server_url"`                                               // server urlAppID       int64                `gorm:"column:app_id;comment:app id" json:"app_id"`                                                            // app idManifest    *PluginManifest      `gorm:"column:manifest;comment:plugin manifest" json:"manifest"`                                              // plugin manifestOpenapiDoc  *Openapi3T           `gorm:"column:openapi_doc;comment:openapi document" json:"openapi_doc"`                                      // openapi documentCreatedAt   int64                `gorm:"column:created_at;not null;autoCreateTime:milli;comment:Create Time in Milliseconds" json:"created_at"` // Create Time in MillisecondsUpdatedAt   int64                `gorm:"column:updated_at;not null;autoUpdateTime:milli;comment:Update Time in Milliseconds" json:"updated_at"` // Update Time in Milliseconds
}// TableName PluginDraft's table name
func (*PluginDraft) TableName() string {return TableNamePluginDraft
}
ToolDraft数据模型

文件位置:backend/domain/plugin/internal/dal/model/tool_draft.gen.go

// ToolDraft tool_draft
type ToolDraft struct {ID              int64      `gorm:"column:id;primaryKey;autoIncrement:true;comment:id" json:"id"`                                          // idPluginID        int64      `gorm:"column:plugin_id;not null;comment:plugin id" json:"plugin_id"`                                           // plugin idSubURL          string     `gorm:"column:sub_url;comment:sub url" json:"sub_url"`                                                          // sub urlMethod          string     `gorm:"column:method;comment:http method" json:"method"`                                                        // http methodActivatedStatus int32      `gorm:"column:activated_status;comment:activated status" json:"activated_status"`                               // activated statusDebugStatus     int32      `gorm:"column:debug_status;comment:debug status" json:"debug_status"`                                           // debug statusOperation       *Operation `gorm:"column:operation;comment:operation info" json:"operation"`                                               // operation infoCreatedAt       int64      `gorm:"column:created_at;not null;autoCreateTime:milli;comment:Create Time in Milliseconds" json:"created_at"` // Create Time in MillisecondsUpdatedAt       int64      `gorm:"column:updated_at;not null;autoUpdateTime:milli;comment:Update Time in Milliseconds" json:"updated_at"` // Update Time in Milliseconds
}

删除操作中的模型特点

  1. 主键定位:ID字段作为主键,是删除操作的核心定位字段,确保精确删除
  2. 权限验证字段:DeveloperID字段用于删除前的权限验证,确保只有开发者可以删除
  3. 关联关系:PluginID字段建立插件与工具的关联关系,支持级联删除
  4. 字段映射:通过gorm标签定义字段与数据库列的映射关系,为删除操作提供准确的数据定位
  5. 约束定义:包含主键、非空、注释等数据库约束,确保删除操作的数据完整性
  6. 复杂类型:Manifest和OpenapiDoc字段存储JSON格式的复杂数据结构
  7. 审计追踪:CreatedAt和UpdatedAt字段支持删除操作的审计追踪和时间记录
  8. JSON序列化:通过json标签支持JSON序列化,便于删除操作的API响应和日志记录

5.4 GORM生成的查询接口

插件查询接口

文件位置:backend/domain/plugin/internal/dal/query/plugin_draft.gen.go

GORM Gen工具生成的类型安全查询接口,为删除插件操作提供了强大的数据访问能力。这些接口确保了删除操作的类型安全性和执行效率。

// pluginDraft plugin_draft
type pluginDraft struct {pluginDraftDoALL         field.AsteriskID          field.Int64  // idSpaceID     field.Int64  // space idDeveloperID field.Int64  // developer idPluginType  field.Int32  // plugin typeIconURI     field.String // icon uriServerURL   field.String // server urlAppID       field.Int64  // app idManifest    field.Field  // plugin manifestOpenapiDoc  field.Field  // openapi documentCreatedAt   field.Int64  // Create Time in MillisecondsUpdatedAt   field.Int64  // Update Time in MillisecondsfieldMap map[string]field.Expr
}
工具查询接口

文件位置:backend/domain/plugin/internal/dal/query/tool_draft.gen.go

// toolDraft tool_draft
type toolDraft struct {toolDraftDoALL             field.AsteriskID              field.Int64  // idPluginID        field.Int64  // plugin idSubURL          field.String // sub urlMethod          field.String // http methodActivatedStatus field.Int32  // activated statusDebugStatus     field.Int32  // debug statusOperation       field.Field  // operation infoCreatedAt       field.Int64  // Create Time in MillisecondsUpdatedAt       field.Int64  // Update Time in MillisecondsfieldMap map[string]field.Expr
}
查询接口定义
type IPluginDraftDo interface {gen.SubQueryDebug() IPluginDraftDoWithContext(ctx context.Context) IPluginDraftDoWithResult(fc func(tx gen.Dao)) gen.ResultInfoReplaceDB(db *gorm.DB)ReadDB() IPluginDraftDoWriteDB() IPluginDraftDo// 删除操作相关方法Delete(conds ...gen.Condition) (gen.ResultInfo, error)Where(conds ...gen.Condition) IPluginDraftDo......
}type IToolDraftDo interface {gen.SubQueryDebug() IToolDraftDoWithContext(ctx context.Context) IToolDraftDo// 删除操作相关方法Delete(conds ...gen.Condition) (gen.ResultInfo, error)Where(conds ...gen.Condition) IToolDraftDo......
}

删除操作相关接口特点

  1. Delete方法:提供类型安全的删除操作,支持条件删除
  2. Where条件:支持复杂的删除条件构建,确保精确删除
  3. 上下文支持:WithContext方法支持请求上下文传递
  4. 事务支持:支持在事务中执行删除操作,确保数据一致性
  5. 调试支持:Debug方法便于删除操作的SQL调试和优化
  6. 关联删除:ToolDraft通过PluginID字段支持级联删除操作
5.5 统一查询入口

文件位置:backend\domain\plugin\internal\dal\query\gen.go

该文件为删除插件操作提供了统一的查询入口和事务支持,确保删除操作的一致性和可靠性。

核心代码:

// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.package queryimport ("context""database/sql""gorm.io/gorm""gorm.io/gen""gorm.io/plugin/dbresolver"
)var (Q          = new(Query)PluginDraft *pluginDraftToolDraft   *toolDraft
)func SetDefault(db *gorm.DB, opts ...gen.DOOption) {*Q = *Use(db, opts...)PluginDraft = &Q.PluginDraftToolDraft = &Q.ToolDraft
}func Use(db *gorm.DB, opts ...gen.DOOption) *Query {return &Query{db:          db,PluginDraft: newPluginDraft(db, opts...),ToolDraft:   newToolDraft(db, opts...),}
}type Query struct {db *gorm.DBPluginDraft pluginDraftToolDraft   toolDraft
}func (q *Query) Available() bool { return q.db != nil }func (q *Query) clone(db *gorm.DB) *Query {return &Query{db:          db,PluginDraft: q.PluginDraft.clone(db),ToolDraft:   q.ToolDraft.clone(db),}
}func (q *Query) ReadDB() *Query {return q.ReplaceDB(q.db.Clauses(dbresolver.Read))
}func (q *Query) WriteDB() *Query {return q.ReplaceDB(q.db.Clauses(dbresolver.Write))
}func (q *Query) ReplaceDB(db *gorm.DB) *Query {return &Query{db:          db,PluginDraft: q.PluginDraft.replaceDB(db),ToolDraft:   q.ToolDraft.replaceDB(db),}
}type queryCtx struct {PluginDraft IPluginDraftDoToolDraft   IToolDraftDo
}func (q *Query) WithContext(ctx context.Context) *queryCtx {return &queryCtx{PluginDraft: q.PluginDraft.WithContext(ctx),ToolDraft:   q.ToolDraft.WithContext(ctx),}
}func (q *Query) Transaction(fc func(tx *Query) error, opts ...*sql.TxOptions) error {return q.db.Transaction(func(tx *gorm.DB) error { return fc(q.clone(tx)) }, opts...)
}func (q *Query) Begin(opts ...*sql.TxOptions) *QueryTx {tx := q.db.Begin(opts...)return &QueryTx{Query: q.clone(tx), Error: tx.Error}
}type QueryTx struct {*QueryError error
}func (q *QueryTx) Commit() error {return q.db.Commit().Error
}func (q *QueryTx) Rollback() error {return q.db.Rollback().Error
}func (q *QueryTx) SavePoint(name string) error {return q.db.SavePoint(name).Error
}func (q *QueryTx) RollbackTo(name string) error {return q.db.RollbackTo(name).Error
}

删除操作查询入口特点

  1. 全局查询对象:提供全局的PluginDraft和ToolDraft查询对象,便于删除操作的统一管理
  2. 事务支持:Transaction方法支持在事务中执行删除操作,确保数据一致性
  3. 读写分离:ReadDB和WriteDB方法支持数据库读写分离,删除操作使用WriteDB
  4. 上下文传递:WithContext方法支持请求上下文在删除操作中的传递
  5. 数据库切换:ReplaceDB方法支持动态切换数据库连接,便于多环境部署
  6. 事务管理:Begin、Commit、Rollback等方法提供完整的事务管理能力
  7. 多表支持:同时支持PluginDraft和ToolDraft两个表的查询操作

5.6 数据访问层删除操作架构总结

删除插件在数据访问层的实现体现了现代Go应用的最佳实践:

技术特点

  1. 类型安全:使用GORM Gen生成类型安全的查询接口,避免SQL注入和类型错误
  2. 分层设计:Repository接口抽象数据访问,DAO实现具体的数据库操作
  3. 错误处理:统一的错误码包装机制,便于上层进行错误分类和处理
  4. 事务支持:完整的事务支持,确保删除操作的原子性
  5. 性能优化:精确的WHERE条件和索引利用,确保删除操作的高效执行
  6. 级联删除:支持插件及其关联工具的级联删除操作

安全保障

  1. 权限验证:通过DeveloperID字段确保只有开发者可以删除自己的插件
  2. 存在性检查:删除前验证插件是否存在,避免无效删除
  3. 物理删除:彻底从数据库中移除记录,确保数据清理的完整性
  4. 审计追踪:完整的时间戳记录,支持删除操作的审计和追踪
  5. 关联清理:确保删除插件时同时清理相关的工具数据

删除操作流程

  1. 接口调用:上层通过Repository接口调用DeleteDraftPlugin方法
  2. 事务开启:开启数据库事务确保操作的原子性
  3. 级联删除:先删除关联的工具数据,再删除插件数据
  4. 事务提交:所有删除操作成功后提交事务
  5. 错误处理:任何步骤失败都会回滚事务并返回错误

这种设计确保了删除插件操作的安全性、可靠性和高性能,为上层业务逻辑提供了坚实的数据访问基础。

数据模型与查询文件依赖关系
数据库表结构 (schema.sql)(plugin_draft、tool_draft表)↓    gen_orm_query.go
模型文件 (model/plugin_draft.gen.go, model/tool_draft.gen.go) - 生成模型↓
查询文件 (query/plugin_draft.gen.go, query/tool_draft.gen.go) - 依赖对应模型↓
统一入口 (query/gen.go) - 依赖所有查询文件

数据访问层架构总结

分层架构

业务服务层 (Service)↓
仓储接口层 (Repository Interface)↓
数据访问层 (DAO Implementation)↓
GORM查询层 (Generated Query)↓
数据模型层 (Generated Model)↓
数据库层 (MySQL)

删除插件在数据访问层的完整流程

  1. 接口定义PluginRepository.DeleteDraftPlugin(ctx, ID) 定义删除操作契约
  2. DAO实现PluginDraftDAO.DeleteWithTX(tx, ID)ToolDraftDAO.DeleteAllWithTX(tx, pluginID) 实现具体删除逻辑
  3. 事务管理:使用事务确保插件和工具数据的一致性删除
  4. 级联删除:先删除工具数据,再删除插件数据
  5. 错误处理:包装删除异常为统一错误码
  6. 结果返回:删除成功返回nil,失败返回包装后的错误

设计优势

  1. 接口抽象:通过Repository接口实现数据访问的抽象化
  2. 代码生成:使用GORM Gen自动生成类型安全的查询代码
  3. 错误处理:统一的错误包装和处理机制
  4. 事务支持:通过context传递支持数据库事务
  5. 删除安全:通过ID精确定位,避免误删除操作
  6. 性能优化:合理的索引设计和查询优化
  7. 可测试性:清晰的分层结构便于单元测试
  8. 可维护性:代码生成减少手工编写,降低维护成本
  9. 级联删除:支持插件及其关联数据的级联删除

删除操作的技术特点

  • 物理删除:当前实现为物理删除,直接从数据库中移除记录
  • 事务操作:使用数据库事务确保插件和工具数据的一致性删除
  • 索引优化:基于主键ID的删除操作,具有最佳的查询性能
  • 错误分类:通过错误码区分不同类型的删除异常
  • 审计支持:可通过数据库日志追踪删除操作的执行情况
  • 关联清理:确保删除插件时同时清理相关的工具数据

6. 基础设施层

基础设施层为插件删除功能提供了核心的技术支撑,包括数据库连接、缓存管理、搜索引擎和事件处理等关键组件。这些组件通过契约层(Contract)和实现层(Implementation)的分离设计,确保了删除操作的可靠性、一致性和高性能。

6.1 数据库基础设施

数据库契约层

文件位置:backend/infra/contract/orm/database.go

package ormimport ("gorm.io/gorm"
)type DB = gorm.DB

设计作用

  • 为GORM数据库对象提供类型别名,统一数据库接口
  • 作为契约层抽象,便于后续数据库实现的替换
  • 为插件相关的数据访问层提供统一的数据库连接接口
MySQL数据库实现

文件位置:backend/infra/impl/mysql/mysql.go

package mysqlimport ("fmt""os""gorm.io/driver/mysql""gorm.io/gorm"
)func New() (*gorm.DB, error) {dsn := os.Getenv("MYSQL_DSN")db, err := gorm.Open(mysql.Open(dsn))if err != nil {return nil, fmt.Errorf("mysql open, dsn: %s, err: %w", dsn, err)}return db, nil
}

在插件删除中的作用

  • PluginDraftDAOToolDraftDAO提供数据库连接,支持插件的删除操作
  • 通过GORM ORM框架,执行安全的plugin_drafttool_draft表删除操作
  • 支持事务处理,确保插件删除过程的数据一致性和原子性
  • 连接池管理,提高插件并发删除的性能和稳定性
  • 支持级联删除,确保插件和相关工具数据的一致性清理

删除操作初始化流程

main.go → application.Init() → appinfra.Init() → mysql.New() → PluginDAO注入 → 执行删除

6.2 ID生成器基础设施

ID生成器契约层

文件位置:backend/infra/contract/idgen/idgen.go

package idgenimport ("context"
)type IDGenerator interface {GenID(ctx context.Context) (int64, error)GenMultiIDs(ctx context.Context, counts int) ([]int64, error)
}
ID生成器实现

文件位置:backend/infra/impl/idgen/idgen.go

type idGenImpl struct {cli       cache.Cmdablenamespace string
}func (i *idGenImpl) GenID(ctx context.Context) (int64, error) {ids, err := i.GenMultiIDs(ctx, 1)if err != nil {return 0, err}return ids[0], nil
}func (i *idGenImpl) GenMultiIDs(ctx context.Context, counts int) ([]int64, error) {// 基于时间戳+计数器+服务器ID的分布式ID生成算法// ID格式:[32位秒级时间戳][10位毫秒][8位计数器][14位服务器ID]// ...
}

在插件删除中的作用

  • 虽然删除操作不需要生成新ID,但ID生成器为删除操作提供了重要支撑
  • 在删除事件发布时,为事件生成唯一的事件ID,确保事件处理的幂等性
  • 支持删除操作的审计日志ID生成,便于操作追踪和问题排查
  • 为删除相关的临时资源(如删除任务、回滚记录)生成唯一标识
  • 为插件删除过程中的中间状态记录生成唯一标识

删除操作中的ID使用流程

PluginService.DeleteDraftPlugin() → 验证插件ID → 执行删除 → 生成事件ID → 发布删除事件

6.3 缓存系统基础设施

缓存契约层

文件位置:backend/infra/contract/cache/cache.go

package cachetype Cmdable interface {Pipeline() PipelinerStringCmdableHashCmdableGenericCmdableListCmdable
}type StringCmdable interface {Set(ctx context.Context, key string, value interface{}, expiration time.Duration) StatusCmdGet(ctx context.Context, key string) StringCmdIncrBy(ctx context.Context, key string, value int64) IntCmd
}
Redis缓存实现

文件位置:backend/infra/impl/cache/redis/redis.go

func New() cache.Cmdable {addr := os.Getenv("REDIS_ADDR")password := os.Getenv("REDIS_PASSWORD")return NewWithAddrAndPassword(addr, password)
}func NewWithAddrAndPassword(addr, password string) cache.Cmdable {rdb := redis.NewClient(&redis.Options{Addr:            addr,Password:        password,PoolSize:        100,MinIdleConns:    10,MaxIdleConns:    30,ConnMaxIdleTime: 5 * time.Minute,DialTimeout:     5 * time.Second,ReadTimeout:     3 * time.Second,WriteTimeout:    3 * time.Second,})return &redisImpl{client: rdb}
}

在插件删除中的作用

  • 权限验证缓存:缓存用户权限信息,快速验证删除权限
  • 插件信息缓存:缓存待删除插件的基本信息,减少数据库查询
  • 分布式锁:防止并发删除同一插件,确保删除操作的原子性
  • 删除状态缓存:临时存储删除操作的状态,支持删除进度查询
  • 事件去重:缓存已处理的删除事件ID,避免重复处理
  • 关联数据缓存:缓存插件关联的工具信息,优化级联删除性能

删除操作缓存使用场景

1. 权限缓存:user_perm:{user_id}:{space_id}:{plugin_id}
2. 插件缓存:plugin_info:{plugin_id}
3. 删除锁:lock:plugin_delete:{plugin_id}
4. 删除状态:delete_status:{plugin_id}:{operation_id}
5. 事件去重:event_processed:{event_id}
6. 工具关联:plugin_tools:{plugin_id}

6.4 ElasticSearch搜索基础设施

ElasticSearch契约层

文件位置:backend/infra/contract/es/es.go

package estype Client interface {Create(ctx context.Context, index, id string, document any) errorUpdate(ctx context.Context, index, id string, document any) errorDelete(ctx context.Context, index, id string) errorSearch(ctx context.Context, index string, req *Request) (*Response, error)Exists(ctx context.Context, index string) (bool, error)CreateIndex(ctx context.Context, index string, properties map[string]any) error
}type BulkIndexer interface {Add(ctx context.Context, item BulkIndexerItem) errorClose(ctx context.Context) error
}
ElasticSearch实现层

文件位置:backend/infra/impl/es/es_impl.go

func New() (es.Client, error) {version := os.Getenv("ES_VERSION")switch version {case "7":return newES7Client()case "8":return newES8Client()default:return newES8Client() // 默认使用ES8}
}

在插件删除中的作用

  • 索引删除:将删除的插件从ES的coze_resource索引中移除
  • 搜索结果更新:确保删除的插件不再出现在搜索结果中
  • 关联数据清理:清理与删除插件相关的搜索索引和元数据
  • 实时同步:插件删除后实时从搜索引擎中移除
  • 批量删除:支持批量删除插件时的批量索引清理
  • 工具索引清理:同时清理插件关联的工具索引数据

删除操作的索引处理

{"operation": "delete","res_id": 123456789,"res_type": 1,"delete_time": 1703123456789,"operator_id": 987654321,"space_id": 111222333
}

删除索引执行流程

1. 用户删除插件 → API Gateway → PluginService.DeleteDraftPlugin()
2. 执行数据库删除 → 发布删除事件 → ES删除处理器
3. 构建删除请求 → esClient.Delete(ctx, "coze_resource", pluginID)
4. 索引清理 → 验证删除结果 → 记录删除日志

6.5 基础设施层架构优势

依赖倒置原则
  • 契约层抽象:业务层依赖接口而非具体实现
  • 实现层解耦:可以灵活替换数据库、缓存、搜索引擎的具体实现
  • 测试友好:通过Mock接口进行单元测试
配置驱动
  • 环境变量配置:通过环境变量控制各组件的连接参数
  • 版本兼容:支持ES7/ES8版本切换,数据库驱动切换
  • 性能调优:连接池、超时时间等参数可配置
高可用设计
  • 连接池管理:数据库和Redis连接池,提高并发性能
  • 错误处理:完善的错误处理和重试机制
  • 监控支持:提供性能指标和健康检查接口
扩展性支持
  • 水平扩展:分布式ID生成支持多实例部署
  • 存储扩展:支持分库分表、读写分离
  • 搜索扩展:支持ES集群部署和索引分片

这种基础设施层的设计为插件删除功能提供了稳定、高效、可扩展的技术底座,确保了删除操作在高并发场景下的安全性、一致性和可靠性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96204.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96204.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/96204.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

案例一: 对基础选择器的使用【网页盒子】

【1】样例&#xff1a;首先&#xff0c;观察到&#xff0c;几个元素竖着排列的&#xff0c;所以使用块级元素&#xff0c;而不是行内元素。【2】代码演示<head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,…

爬虫项目优化:如何用 Redis 实现 “断点续爬”?避免重复采集电商数据

在电商数据采集场景中&#xff0c;爬虫常因网络波动、服务器重启、IP 封禁等问题中断。若缺乏断点续爬机制&#xff0c;重启后需从头开始&#xff0c;不仅浪费带宽与时间&#xff0c;还可能因重复采集导致数据冗余。Redis 凭借其高性能、原子操作、多样数据结构的特性&#xff…

决策树概念与原理

决策树简介决策树是一种树形结构树中每个内部节点表示一个特征上的判断&#xff0c;每个分支代表一个判断结果的输出&#xff0c;每个叶子节点代表一种分类结果(仅举例无其他意义或隐喻)就像一个女孩去相亲&#xff0c;那么首先询问是否大于30&#xff0c;大于则不见&#xff0…

SQL面试题及详细答案150道(116-135) --- 高级查询与函数篇

《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。 前后端面试题-专栏总目录 文章目录 一、本文面试题目录 116. 如何使用CASE语句实…

VeRL:强化学习与大模型训练的高效融合框架

本文由「大千AI助手」原创发布&#xff0c;专注用真话讲AI&#xff0c;回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我&#xff0c;一起撕掉过度包装&#xff0c;学习真实的AI技术&#xff01; 1 概述&#xff1a;VeRL的起源与核心价值 VeRL&#xff08;Versatile…

2. 计算机系统基础知识

1 计算机系统概述 计算机系统 (Computer System) 是指用于数据管理的计算机硬件、软件及网络组成的系统。 计算机系统可划分为硬件(子系统)和软件(子系统)两部分。硬件由机械、电子元器件、磁介质和光介质等物理实体构成&#xff0c;例如处理器(含运算单元和控制单元)、存储器、…

国产EtherCAT从站芯片FCE1353与N32G435 MCU功能板测试流程

上期推荐&#xff0c;我们在前期介绍了FCE1353与国民N32G435 MCU开发板的基本情况&#xff0c;本期主要介绍此开发板的测试流程&#xff0c;以便用户拿到此板做功能验证、兼容性测试、可靠性测试时更加便捷地提高开发验证效率。01概述FCE1353_N32G435RBL7_GPIO_V1 开发板主要通…

向日葵亮点16功能解析:被控端“快速解锁”

向日葵16重磅上线&#xff0c;本次更新新增了诸多实用功能&#xff0c;提升远控效率&#xff0c;实现应用融合突破设备边界&#xff0c;同时全面提升远控性能&#xff0c;操作更顺滑、画质更清晰&#xff01;无论远程办公、设计、IT运维、开发还是游戏娱乐&#xff0c;向日葵16…

深度解析:IService 与 ServiceImpl 的区别

在使用 MyBatis-Plus 开发业务逻辑时&#xff0c;IService 和 ServiceImpl 是经常遇到的两个核心类。很多初学者会疑惑&#xff1a; 为什么要定义 IService&#xff1f;ServiceImpl 又解决了什么问题&#xff1f;它们之间到底有什么区别与联系&#xff1f; 本文将结合源码与应用…

YOLO12 改进、魔改|通道自注意力卷积块CSA-ConvBlock,通过动态建模特征图通道间的依赖关系,优化通道权重分配,在强化有效特征、抑制冗余信息

在分割的研究中&#xff0c;传统卷积神经网络&#xff08;CNN&#xff09;存在两大关键问题&#xff1a;一是池化操作虽能降低计算复杂度&#xff0c;却会导致特征图中有效空间信息丢失&#xff0c;尤其太阳暗条这类不规则、精细结构的特征易被削弱&#xff1b;二是传统 CNN 对…

JuiceFS分布式文件系统

对象存储虽然具备极高的扩展性和成本优势&#xff0c;却缺乏对POSIX语义的支持&#xff0c;导致许多应用无法直接使用。正是在这样的背景下&#xff0c;JuiceFS 应运而生——它巧妙地融合了对象存储的弹性与传统文件系统的易用性&#xff0c;为现代应用提供了一种全新的存储解决…

nginx配置前端请求转发到指定的后端ip

nginx conf配置 配置把“前端静态文件”和“后端接口”统一收在 同一个 server{} 块 里&#xff0c;通过 两条 location 做分流&#xff0c;其中 /api 这条 location 用到了一点“小技巧”把路径裁掉后再转发。下面按执行顺序逐句拆解&#xff0c;告诉你“请求是怎么被转发到 1…

HTML 各种标签的使用说明书

HTML 各种标签的使用说明书 1. HTML 简介 HTML&#xff08;HyperText Markup Language&#xff0c;超文本标记语言&#xff09;是用于创建网页的标准标记语言。它使用一系列标签来描述网页的结构和内容&#xff0c;这些标签被浏览器解释并渲染成用户看到的网页。HTML是构建We…

从关键词到语义理解:小陌引擎如何重构AI搜索优化逻辑?

引言&#xff1a;AI搜索时代的范式转变在传统互联网时代&#xff0c;SEO&#xff08;搜索引擎优化&#xff09;是企业数字营销的核心策略&#xff0c;通过关键词密度、外链建设等技术手段提升网页在搜索引擎结果页&#xff08;SERP&#xff09;中的排名。然而&#xff0c;随着生…

ADE explorer遇到XVFB服务器的问题

遇到这个报错&#xff0c;是因为服务器没有安装xvfb的原因。yum install Xvfb即可解决问题。

期权的套利怎么理解?

期权套利是利用期权价格之间的不合理偏差&#xff0c;通过构建对冲组合获取无风险利润的策略。其核心逻辑基于“无套利定价原则”——若存在价格偏差&#xff0c;市场力量会迅速修正&#xff0c;套利者通过反向操作锁定利润。期权的套利怎么理解&#xff1f;一、主要套利类型与…

RabbitMQ 重试机制 和 TTL

目录 1. 重试机制 1.1 简介 1.2 配置文件 1.3 消费者确认机制为 auto 时 1.4 消费者确认机制为 manual 时 2. TTL 2.1 设置消息的过期时间 2.2 设置队列的过期时间 2.3 给过期队列中消息设置过期时间 1. 重试机制 1.1 简介 在消息传递过程中, 可能会遇到各种问题, …

四、FVP启动linux

目录 1 实验目的及环境 1.1 实验目的 1.2 实验环境 1.2.1 拉取代码 1.2.2搭建交叉编译环境 2 相关镜像编译 2.1 TF-A镜像编译 2.2 U-Boot镜像编译 2.3 Linux Kernel镜像编译 2.4 构建跟文件系统 3 启动linux内核 3.1 启动脚本构建 3.2 启动Linux内核 1 实验目的及环境 1.1 实验…

浅聊一下微服务的服务保护

在微服务架构里&#xff0c;服务间调用关系错综复杂&#xff0c;一个服务出问题很可能引发连锁反应&#xff0c;也就是 “雪崩”。今天就带大家从零开始学习 Sentinel&#xff0c;这款阿里开源的微服务保护工具&#xff0c;帮你解决雪崩难题&#xff0c;做好流量控制、隔离降级…

ECharts Gallery:Apache官方数据可视化模板库,助你快速制作交互图表并实现深度定制

你有没有过这种时候&#xff1f;手里攥着一堆 Excel 数据&#xff0c;想做个直观的图表给同事看&#xff0c;用 Excel 自带的图表吧&#xff0c;样式丑不说&#xff0c;稍微复杂点的交互&#xff08;比如点击柱子显示详情&#xff09;根本做不了&#xff1b;想自己用代码写吧&a…