3. 应用服务层
PluginApplicationService初始化
文件位置:backend/application/plugin/plugin.go
PluginApplicationService是插件应用服务层的核心组件,专门负责处理插件资源的删除等业务逻辑,是连接API层和领域层的重要桥梁。在用户点击"资源库" → 在表格中点击要删除的插件行最右边的"..."号 → 最后点击弹出菜单中的"删除"菜单的场景中,该服务承担着核心的删除业务处理职责。
服务结构定义
文件位置:backend/application/plugin/plugin.go
go
type PluginApplicationService struct {
DomainSVC service.PluginService
toolRepo repository.ToolRepository
eventbus search.ResourceEventBus
}
var PluginSVC = &PluginApplicationService{}
服务初始化实现
文件位置:backend/application/plugin/init.go
go
// InitService 初始化插件应用服务,注入领域服务依赖
func InitService(pluginRepo repository.PluginRepository, toolRepo repository.ToolRepository, eventbus ResourceEventBus) *PluginApplicationService {
// 创建插件领域服务
pluginDomainSVC := service.NewService(pluginRepo, toolRepo)
// 初始化应用服务
service := &PluginApplicationService{
DomainSVC: pluginDomainSVC,
toolRepo: toolRepo,
eventbus: eventbus,
}
return service
}
服务初始化特点:
- 依赖注入:通过Repository接口注入数据访问能力,实现依赖倒置
- 事件驱动架构:集成资源事件总线,支持异步事件处理和数据同步
- 领域服务协调:封装插件领域服务,提供应用层的业务编排
- 多仓储支持:同时注入插件和工具仓储,支持复杂的插件管理操作
删除插件核心实现
DelPlugin方法详解
文件位置:backend/application/plugin/plugin.go
当用户在资源库中点击要删除的插件行最右边的"..."号,然后点击弹出菜单中的"删除"菜单时,前端会调用DelPlugin
方法来删除指定的插件资源。
go
func (p *PluginApplicationService) DelPlugin(ctx context.Context, req *pluginAPI.DelPluginRequest) (resp *pluginAPI.DelPluginResponse, err error) {
_, err = p.validateDraftPluginAccess(ctx, req.PluginID)
if err != nil {
return nil, errorx.Wrapf(err, "validateDelPluginRequest failed")
}
err = p.DomainSVC.DeleteDraftPlugin(ctx, req.PluginID)
if err != nil {
return nil, errorx.Wrapf(err, "DeleteDraftPlugin failed, pluginID=%d", req.PluginID)
}
err = p.eventbus.PublishResources(ctx, &searchEntity.ResourceDomainEvent{
OpType: searchEntity.Deleted,
Resource: &searchEntity.ResourceDocument{
ResType: resCommon.ResType_Plugin,
ResID: req.PluginID,
UpdateTimeMS: ptr.Of(time.Now().UnixMilli()),
},
})
if err != nil {
return nil, errorx.Wrapf(err, "publish resource '%d' failed", req.PluginID)
}
resp = &pluginAPI.DelPluginResponse{}
return resp, nil
}
方法功能特点:
- 权限验证:通过validateDraftPluginAccess验证用户对插件的访问权限
- 领域服务调用:调用领域服务层的DeleteDraftPlugin方法执行删除逻辑
- 事件发布:删除完成后发布删除事件,支持搜索索引更新等下游处理
- 错误处理:完善的错误处理机制,包装错误信息便于调试
- 时间戳记录:在事件中记录删除时间,便于审计和追踪
删除插件业务流程
删除插件的完整业务流程包括以下几个关键步骤:
- 权限验证:验证用户对要删除插件的访问权限
- 执行删除操作:调用领域服务执行实际的删除操作
- 事件发布:发布删除事件,通知其他系统组件进行相应处理
- 返回响应:返回删除操作的结果
删除操作的安全性保障:
- 权限控制:严格的插件访问权限验证,防止越权删除
- 数据一致性:通过事务确保删除操作的原子性
- 事件驱动:异步事件处理,确保相关数据的同步更新
- 错误处理:完善的错误处理机制,确保系统稳定性
4. 领域服务层
插件领域服务层架构
插件领域服务层是Coze Studio中处理插件业务逻辑的核心层,负责插件资源的删除、管理和业务规则实现。该层采用领域驱动设计(DDD)模式,将业务逻辑与数据访问分离,确保代码的可维护性和可扩展性。
插件领域服务接口定义
文件位置:backend/domain/plugin/service/service.go
插件领域服务接口定义了插件管理的核心业务能力,包括插件资源的完整生命周期管理。
go
type PluginService interface {
// 删除草稿插件
DeleteDraftPlugin(ctx context.Context, pluginID int64) error
// 其他插件管理方法
CreateDraftPlugin(ctx context.Context, req *CreateDraftPluginRequest) (*CreateDraftPluginResponse, error)
GetDraftPlugin(ctx context.Context, pluginID int64) (*entity.PluginInfo, bool, error)
UpdateDraftPlugin(ctx context.Context, req *UpdateDraftPluginRequest) error
}
核心接口功能:
- 插件资源管理:创建、获取、更新、删除用户自定义的插件资源
- 删除操作核心:DeleteDraftPlugin方法是删除插件的核心业务接口
- 草稿管理:专门处理草稿状态的插件,支持开发过程中的迭代
- 业务规则封装:封装插件相关的业务逻辑和验证规则
- 数据一致性:确保插件数据的完整性和一致性
插件领域服务实现
文件位置:backend/domain/plugin/service/plugin_draft.go
插件服务实现类包含了所有插件相关业务逻辑的具体实现,依赖于仓储层进行数据持久化。
go
type pluginServiceImpl struct {
pluginRepo repository.PluginRepository
toolRepo repository.ToolRepository
}
func NewService(pluginRepo repository.PluginRepository, toolRepo repository.ToolRepository) PluginService {
return &pluginServiceImpl{
pluginRepo: pluginRepo,
toolRepo: toolRepo,
}
}
// DeleteDraftPlugin 删除草稿插件
func (p *pluginServiceImpl) DeleteDraftPlugin(ctx context.Context, pluginID int64) (err error) {
return p.pluginRepo.DeleteDraftPlugin(ctx, pluginID)
}
删除操作实现特点:
- 依赖注入:通过Repository接口注入数据访问能力,实现松耦合
- 仓储模式:使用Repository模式进行数据访问抽象,隔离业务逻辑与数据层
- 简洁删除:DeleteDraftPlugin方法实现简洁,直接调用仓储层删除操作
- 错误传播:统一的错误处理和传播机制,确保删除异常的正确处理
- 业务隔离:领域服务层专注于业务逻辑,数据操作委托给仓储层
- 多仓储协调:同时管理插件和工具仓储,支持复杂的插件删除操作
DeleteDraftPlugin方法详解:
- 参数简洁:只需要pluginID参数,通过ID精确定位要删除的插件
- 错误处理:直接传播仓储层的错误,保持错误信息的完整性
- 返回值:删除成功返回nil,失败返回具体错误信息
- 业务纯净:不包含权限验证等应用层逻辑,专注于领域层的删除操作
插件实体定义
文件位置:backend/domain/plugin/entity/plugin.go
插件实体定义了插件资源的核心数据结构,包含了插件的所有关键属性。
go
type PluginInfo struct {
ID int64 // 插件唯一标识
PluginType common.PluginType // 插件类型(本地/远程)
SpaceID int64 // 所属空间ID,支持多租户隔离
DeveloperID int64 // 开发者ID
APPID *int64 // 关联应用ID
IconURI *string // 插件图标URI
ServerURL *string // 服务器URL
Manifest *model.PluginManifest // 插件清单信息
OpenapiDoc *model.Openapi3T // OpenAPI文档
CreatedAt int64 // 创建时间戳
UpdatedAt int64 // 更新时间戳
}
实体设计特点:
- 基础信息:包含ID、类型、空间等基本属性,满足插件的基本信息需求
- 类型支持:PluginType字段支持本地和远程插件类型,灵活适配不同场景
- 多租户支持:SpaceID字段支持多租户和空间隔离,确保数据安全
- 开发者管理:DeveloperID字段支持开发者权限控制和资源归属管理
- 应用关联:APPID字段支持插件与应用的关联关系
- 配置管理:Manifest和OpenapiDoc字段存储插件的配置和API文档
- 时间追踪:CreatedAt和UpdatedAt支持创建和更新时间追踪,便于审计和版本管理