跳到主要内容
版本:0.4.x

基本介绍

为提升框架整体的灵活性与可扩展性,主框架采用领域驱动的设计思路对核心能力进行建模,并以解耦方式组织各领域能力的实现与契约。

  • apps/lina-core/pkg/plugin目录作为公开的领域契约边界,向插件暴露稳定的领域服务接口。
  • 源码插件通过pluginhost.Services消费完整的capability.Services目录。
  • 动态插件通过pluginbridge.Default()返回的pluginbridge.Services消费已经发布为hostServices的能力子集。

组件结构

路径职责
capability/聚合稳定宿主能力,包含Services、插件作用域服务绑定和各领域窄接口;源码插件直接使用完整目录,动态插件使用已发布的桥接子集
pluginhost/源码插件宿主命名空间,提供编译期注册接口层和运行期回调契约
pluginbridge/动态插件桥接命名空间,提供pluginbridge.Default()/pluginbridge.New()运行时能力目录、Wasm执行契约和hostServices编解码

领域能力概览

方法领域文档SPI扩展说明
AI()AI能力支持聚合文本、图片、向量、音频、视觉、文档、安全和视频子能力
APIDoc()接口文档-解析路由操作键、本地化模块标签和操作摘要
Auth()认证与授权-认证令牌签发、租户切换、模拟令牌和授权权限视图读取与判断
Users()用户管理-用户视图、搜索和可见性校验
BizCtx()业务上下文-读取当前请求用户、租户、模拟登录和平台绕过状态
Cache()缓存能力-插件作用域运行时缓存
Dict()字典能力-字典类型和值的生命周期管理、标签解析和缓存刷新
Files()文件能力-文件视图、上传、流式打开和可见性校验
HostConfig()配置管理-读取宿主配置值;动态插件读取时必须声明keys
I18n()国际化能力-源码插件运行时翻译能力;动态插件不开放对应host service
Jobs()定时任务-定时任务生命周期管理
Manifest()清单资源-读取当前已打包的插件manifest/下的只读资源
Notifications()通知能力-通知消息的生命周期管理
Org()组织管理支持可选组织能力,部门和岗位的生命周期管理
Plugins()插件治理-聚合插件注册表、插件配置、插件状态和生命周期子能力
Route()动态路由-读取当前动态路由元数据
Sessions()在线会话-在线会话搜索、批量读取和吊销
Storage()文件能力支持插件作用域对象存储操作
Tenant()租户能力支持可选租户能力,读取当前租户、可见性、切换校验和源码插件租户过滤
Lock()分布式锁-插件可见的分布式锁获取、续租和释放

插件作用域能力会由宿主绑定插件身份。例如Plugins().Config()只读取当前插件自己的config.yamlManifest()只读取当前插件的manifest/资源,AI()会把来源插件ID注入后续提供方请求。

能力生命周期

插件能力分为声明期和运行期两个阶段。

  • 声明期是插件的静态注册和发现阶段,主框架在业务执行前使用声明输出构建治理状态。
  • 运行期是插件业务逻辑执行阶段,插件消费主框架提供的领域能力服务。

声明期能力

声明期能力是插件的静态注册输出。源码插件在编译期通过pluginhost.Declarations注册,动态插件通过plugin.yaml清单和pluginbridge.Declarations声明。

声明期能力的详细设计和使用方式请参阅声明期能力概览

源码插件声明期

源码插件通过pluginhost.Declarationsinit()中注册以下声明:

声明入口功能说明
ID()返回与plugin.yaml一致的稳定插件标识
Assets()绑定插件嵌入文件系统,包含清单、前端页面、SQLi18n资源
Lifecycle()注册安装、升级、禁用、卸载、租户禁用、租户删除和安装模式变更等16个生命周期回调
Hooks()订阅主框架扩展点事件,例如auth.login.succeededplugin.enabledsystem.started
HTTP()注册插件HTTP路由贡献回调,由主框架启动时统一触发
Jobs()注册定时任务贡献回调,由主框架调度时统一触发
Providers()声明领域能力提供方工厂,例如ProvideTenantProvideOrgProvideAIText
Access()注册菜单过滤和权限过滤回调,用于运行时动态调整工作台导航和权限

动态插件声明期

动态插件通过plugin.yaml清单和构建期契约表达声明:

声明来源功能说明
plugin.yaml声明插件身份、版本、依赖、菜单、权限、多租户策略、公开静态资源和hostServices授权申请
Routes()声明路由组绑定,指定API前缀和路由包
Jobs()通过host-service调用注册定时任务契约
WASM自定义段.wasm产物中嵌入ABI版本、运行时类型、编解码器和导出函数名等元数据
protocol.BridgeSpec定义桥接ABI契约,包括版本号、运行时类型、编解码方式和alloc/execute导出名称

运行期能力

运行期能力是插件业务逻辑执行时可用的服务。源码插件和动态插件共享宿主领域能力模型,但公开入口不同。

源码插件运行期

源码插件通过pluginhost.Services访问运行期能力。该接口内嵌capability.Services,直接暴露全部领域能力方法。

动态插件运行期

动态插件通过pluginbridge.Default()访问已发布的运行期能力。所有调用经由WASI host call传输,由宿主按hostServices授权快照校验后分发执行。动态插件访问的是动态服务目录中的能力子集,并拥有三个专属能力:

能力入口功能说明
已发布领域能力例如AIAuthCacheStorage等能力,通过host-call桥接访问;I18n()不发布为动态hostServices
Runtime()专属能力:日志写入、插件状态读写、时间获取、UUID生成、节点身份读取
Network()专属能力:受治理的出站HTTP请求,需在plugin.yaml中声明授权目标地址
RecordStore()专属能力:data服务的类ORM封装层,只能访问声明的插件自有表

源码插件与动态插件的能力差异

源码插件通过capability.Services访问完整的领域能力,包括读取和写入操作(例如Jobs().Run()Sessions().Revoke()Notifications().Send()等)。这些写操作经过状态、目标、租户、审计等治理校验后执行。

动态插件的pluginbridge.Services接口只暴露已发布为hostServices的能力子集。动态插件只能调用已经写入plugin.yaml声明、经过宿主授权并注册到WASM host-service分发器中的具体方法。几乎所有领域能力都已对动态插件开放了读写接口——例如sessions动态服务包含sessions.revoke强退命令,jobs动态服务包含jobs.runjobs.status.set等写操作,dictfileshostconfigorgusers等服务也同时提供了CreateUpdateDelete等完整的生命周期管理方法。插件作者应参考下方动态服务目录表格确认各服务的具体方法列表。

SPI架构设计

部分领域能力属于可选框架能力——它们不是主框架内置的,而是由提供方插件实现具体逻辑后注入到宿主运行时。当前采用SPI模式的能力比如AIOrgTenant等,对应的官方提供方插件分别为linapro-ai-corelinapro-org-corelinapro-tenant-core

架构设计

SPIService Provider Interface)模式的核心思想是将能力契约与能力实现分离。宿主定义领域能力的公开接口(即SPI契约),提供方插件负责实现具体业务逻辑。宿主通过延迟构造避免启动阶段对可选插件的强依赖——只有当能力首次被消费时,宿主才会实例化提供方。

设计要点说明
延迟构造宿主只在能力首次被消费时构造提供方实例,避免启动阶段强依赖可选插件
安全降级没有可用提供方时,能力返回空结果或不可用状态,而非nil或错误
来源注入宿主通过ProviderEnv向提供方注入请求上下文、插件身份和辅助能力
启用状态隔离提供方状态独立于业务入口可见性——插件的业务入口可能对当前租户不可见,但仍可作为平台能力提供方可用

SPI服务注册

源码插件通过pluginhost.Declarations.Providers()声明SPI工厂。每个工厂是一个构造函数,接收ProviderEnv参数并返回提供方实例:

ProviderEnv是宿主向提供方注入的运行期上下文,通常包含:

注入项说明
插件身份当前提供方插件的ID,用于审计和隔离
请求上下文当前请求的租户、用户等业务上下文
辅助能力提供方实现所需的宿主能力,例如TenantFilter、用户视图等

SPI提供方状态检查

宿主通过Plugins().State().IsProviderEnabled()判断提供方是否可用。该检查与IsEnabled语义不同:

检查方法语义适用场景
IsEnabled插件的业务入口对当前租户是否可见菜单过滤、路由可见性、权限过滤
IsProviderEnabled插件是否平台启用且可承接框架能力提供方调用AIOrgTenant等能力调用前检查

提供方检查确保即使业务入口被租户级禁用,平台级能力仍可正常服务。

插件实现SPI提供方

源码插件实现SPI提供方分为注册和实现两个步骤。以Org能力为例:

注册SPI工厂:

提供方插件在init()中通过Providers()声明入口注册工厂函数:

func init() {
plugin := pluginhost.NewDeclarations("my-author-my-org-provider")
if err := plugin.Providers().ProvideOrg(func(ctx context.Context, env orgspi.ProviderEnv) (orgspi.Provider, error) {
return &myOrgProvider{env: env}, nil
}); err != nil {
panic(err)
}

if err := pluginhost.RegisterSourcePlugin(plugin); err != nil {
panic(err)
}
}

实现SPI契约:

提供方需要实现能力领域包中定义的Provider接口。以orgcap.Provider为例,提供方需要实现部门视图、岗位视图等完整组织能力:

type myOrgProvider struct {
env orgcap.ProviderEnv
}

func (p *myOrgProvider) ListUserDeptAssignments(ctx context.Context, userIDs []string) ([]DeptAssignment, error) {
// 查询提供方自己的组织数据
// 可通过 p.env 访问宿主注入的辅助能力
}

func (p *myOrgProvider) GetUserDeptInfo(ctx context.Context, userID string) (*DeptInfo, error) {
// 实现部门信息查询
}

Tenant能力额外提供tenantcap.Resolver接口,负责从HTTP请求中解析租户身份,可按请求头、域名、路径、令牌或其他策略组成责任链。

动态插件与SPI

动态插件不能直接注册SPI工厂,因为提供方需要实现Go接口并运行在宿主进程中。动态插件通过以下方式与SPI能力交互:

交互方式说明
消费SPI能力通过hostServices声明调用已发布的SPI能力方法,例如service: aiservice: orgservice: tenant
检查SPI提供方状态通过plugins.provider_enabled.check动态方法判断提供方是否可用
状态查询通过capability.availablecapability.status动态方法查询能力可用性和活跃提供方

动态插件在plugin.yaml中声明对SPI能力的消费:

hostServices:
- service: ai
methods:
- text.generate
- service: org
methods:
- users.dept_name.get
- service: tenant
methods:
- tenants.current

动态hostServices

动态插件不能直接访问宿主实现包,只能通过plugin.yaml中的hostServices声明需要调用的宿主服务。一个典型的plugin.yaml中的hostServices声明如下:

hostServices:
- service: runtime
methods:
- log.write
- state.get
- state.set
- service: storage
methods:
- put
- get
- list
resources:
paths:
- exports/
- service: data
methods:
- list
- get
- create
resources:
tables:
- plugin_demo_reports
- service: network
methods:
- request
resources:
- url: https://api.example.com/v1/*
- service: hostconfig
methods: [get]
resources:
keys:
- workspace.basePath
- service: manifest
methods: [get]
resources:
paths:
- profile.yaml
- service: ai
methods:
- text.generate

资源声明形态

资源类型声明字段服务
none不声明resourcesruntimeapidocauthaiusersbizctxdictfilesjobsnotificationspluginsroutesessionsorgtenant
pathresources.pathsstoragemanifest
tableresources.tablesdata
keyresources.keyshostconfig
resourceresources[].urlresources[].ref及服务专属属性networkcachelocknotifications(仅messages.send

生产校验会要求data服务表属于插件自有命名空间。动态插件不得声明sys_*这类宿主核心表,也不应把宿主表名作为插件数据能力的目标。

动态服务目录

服务领域文档资源类型方法
aiAI能力nonetext.generatetext.method_status.getai.methods.status.batch_getimage.generateimage.editembedding.createaudio.transcribeaudio.synthesizevision.analyzedocument.analyzedocument.citesafety.moderatevideo.generatevideo.editvideo.extendvideo.operation.getvideo.operation.cancel
apidoc接口文档noneroute_text.resolveroute_texts.resolveroute_title_operation_keys.find
auth认证与授权nonetoken.tenant.selecttoken.tenant.switchtoken.impersonation_token.issuetoken.impersonation_token.revokeauthz.permissions.batch_getauthz.permissions.batch_hasauthz.permissions.hasauthz.users.platform_admin.checkauthz.role_permissions.replace
bizctx业务上下文nonecurrent.get
cache缓存能力resourcegetget_manysetset_manydeletedelete_manyincrexpire
data数据库操作tablelistgetbatch_getcreateupdatedeletetransaction
dict字典能力nonedict.refreshdict.type.getdict.type.batch_getdict.type.listdict.type.visible.ensuredict.type.keys.visible.ensuredict.type.createdict.type.updatedict.type.deletedict.value.getdict.value.batch_getdict.value.labels.resolvedict.value.listdict.value.visible.ensuredict.value.values.visible.ensuredict.value.createdict.value.updatedict.value.deletedict.value.by_type.delete
files文件能力nonefiles.batch_getfiles.listfiles.visible.ensurefiles.uploadfiles.create_from_storagefiles.metadata.updatefiles.deletefiles.delete_many
hostconfig配置管理keygetsys_config.getsys_config.value.setsys_config.reset
jobs定时任务nonejobs.batch_getjobs.listjobs.visible.ensurejobs.createjobs.updatejobs.deletejobs.runjobs.status.setjobs.register
lock分布式锁resourceacquirerenewrelease
manifest清单资源pathgetget_manylist
network网络访问resourcerequest
notifications通知能力读取无资源;messages.send使用resources[].refmessages.batch_getmessages.listmessages.by_source.batch_getmessages.visible.ensuremessages.sendmessages.deletemessages.by_source.deletemessages.mark_readmessages.mark_unread
org组织管理nonecapability.availablecapability.statusorg.assignment.user_profiles.batch_getorg.department.tree.listorg.department.batch_getorg.department.listorg.department.createorg.department.updateorg.department.deleteorg.post.batch_getorg.post.options.listorg.post.createorg.post.updateorg.post.deleteorg.department.visible.ensure_manyorg.post.visible.ensure_manyorg.assignment.by_user.replaceorg.assignment.by_user.cleanup
plugins插件治理noneplugins.current.getplugins.batch_getplugins.registry.listplugins.tenant.listconfig.getplugins.state.enabled.checkplugins.state.provider_enabled.checkplugins.state.enabled_authoritative.checkplugins.lifecycle.tenant_plugin_disable.ensureplugins.lifecycle.tenant_plugin_disabled.notifyplugins.lifecycle.tenant_delete.ensureplugins.lifecycle.tenant_deleted.notify
route动态路由nonemetadata.get
runtime运行时能力nonelog.writestate.getstate.get_manystate.setstate.set_manystate.deletestate.delete_manyinfo.nowinfo.uuidinfo.node
sessions会话管理nonesessions.current.getsessions.listsessions.batch_getsessions.users.online.batch_getsessions.visible.ensuresessions.revokesessions.revoke_many
storage文件能力pathputput.initput.chunkput.commitput.abortgetdeletedelete.batchlistlist.cursorstatstat.batch
tenant多租户能力nonecapability.availablecapability.statustenant.context.currenttenant.context.infotenant.context.platform_bypasstenant.directory.batch_gettenant.directory.listtenant.membership.validatetenant.membership.list_by_usertenant.directory.visible.ensure_manytenant.plugins.enabled.settenant.plugins.defaults.provisiontenant.filter.context
users用户管理noneusers.current.getusers.batch_getusers.resolve.batchusers.listusers.visible.ensureusers.createusers.updateusers.deleteusers.status.setusers.password.resetusers.assignment.roles.replace

动态插件专属能力

Runtime()Network()RecordStore()pluginbridge.Default()返回目录上的动态插件专属能力。它们不属于capability.Services,因为源码插件已经运行在宿主进程内,可以使用宿主原生等价能力。

能力公开入口说明
Runtime()pluginbridge.Default().Runtime()动态插件通过WASI host-service客户端写日志、读写状态、读取时间、生成UUID和读取节点身份;源码插件直接使用宿主原生日志和运行期上下文
Network()pluginbridge.Default().Network()动态插件通过host-service授权访问受治理的出站HTTP;源码插件使用宿主原生HTTP client或注入的领域服务
RecordStore()pluginbridge.Default().RecordStore()动态插件使用pluginbridgefacade封装data host-service协议和类型化查询计划;源码插件使用自有DAO或提供方接缝

相关文档