Coze源碼分析-資源庫-刪除插件-后端源碼-數據訪問和基礎設施層

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…