☰
xberg Kotlin (Android) 插件 API:ValidatorBridge.clearAll() 清除验证器注册表实战
2026/10/8 19:13:46 网站建设 项目流程
  • 后端
  • AI 应用
  • NLP

【免费下载链接】xberg

Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.

项目地址:https://gitcode.com/gh_mirrors/kr/xberg
点击查看免费下载

本指南聚焦 xberg 在 Kotlin (Android) 平台上的插件管理 API 中"清除全部验证器"这一操作,讲解ValidatorBridge.clearAll()的调用方式、它在 Kotlin 侧与 Rust 原生层之间的完整调用链,以及底层验证器注册表在清除时的实际行为(shutdown 语义、错误传播与空注册表处理)。读完本文,你将掌握在 Android 应用里安全地清空验证器、与listValidators()配合做状态校验的完整实战方案,并理解这一操作在多语言插件系统中为何被定义为 safe(无副作用)。

一、场景与定位:为什么需要"清空验证器"

在 xberg 的插件体系中,验证器(Validator)是一个可插拔组件:每个验证器实现validate()回调,在文档抽取流程完成后对ExtractedDocument进行校验。应用在运行期会动态注册验证器(例如按用户设置或租户配置注入不同的校验规则)。与之对应的生命周期操作自然包括"按名注销单个验证器"和"一次性清空全部验证器"。

"清空全部"最常见的三个使用场景:

  1. 配置热切换:应用切换校验策略集时,先clearAll()再批量注册新验证器,避免旧规则残留影响新流程;
  2. 应用退出 / 页面销毁:释放验证器持有的原生资源,防止内存泄漏;
  3. 测试与夹具复位:在单元测试或 e2e 测试的tearDown中复位全局注册表,保证用例之间状态隔离。

这一点在仓库的 e2e 夹具元数据中也有印证:fixture 的side_effects被标记为safe,表示该操作不产生对外部系统的副作用,可以被测试框架安全地反复调用(见 fixtures/plugin_api/validators_clear.json)。同时,由于该操作依赖"宿主语言回调"这一机制,C API 不暴露对应的注册/清空调用,因此该 fixture 在c语言上被明确跳过(skip.languages: ["c"]),而 Kotlin (Android) 在内的其他语言均保留此能力。

二、Kotlin 侧最小调用示例

关联文档给出的 Kotlin (Android) 端代码如下(原始片段见 validators_clear.md):

import io.xberg.* fun main() { ValidatorBridge.clearAll() }

这段代码的核心只有一行:ValidatorBridge.clearAll()。它不接收参数、不返回业务结果(Kotlin 侧为Unit),语义即"清空全局验证器注册表并释放全部已注册验证器"。

配套操作:清空后如何验证

"Clear all validators and verify list is empty" 是夹具的完整语义——清空之后必须验证列表为空。验证方式使用同目录下的配套片段(见 validators_list.md):

import io.xberg.* fun main() { val result = Xberg.listValidators() println(result) }

组合起来的完整模式:

import io.xberg.* fun resetValidators() { ValidatorBridge.clearAll() // 1. 清空并释放全部验证器 val remaining = Xberg.listValidators() // 2. 列出剩余验证器 println("remaining validators: $remaining") // 3. 确认列表为空 check(remaining.isEmpty()) { "validators registry should be empty after clearAll" } }

在真实测试中,这正是 e2e 断言的做法:fixture 的call字段指向clear_validators,断言类型为not_error,即调用成功且不抛错即为通过(见 fixtures/plugin_api/validators_clear.json 的assertions段)。

三、调用链拆解:从 Kotlin 到 Rust 原生层

3.1 Kotlin 侧的桥接对象

ValidatorBridge在仓库中的实现见 ValidatorBridge.kt:

object ValidatorBridge { private val registered = mutableMapOf<String, IValidator>() fun register(impl: IValidator): Unit { val name = impl.name() registered[name] = impl XbergBridge.nativeRegisterValidator(ValidatorJniDispatcher(impl)) } fun unregister(name: String): Unit { registered.remove(name) XbergBridge.nativeUnregisterValidator(name) } fun clearAll(): Unit { registered.clear() XbergBridge.nativeClearValidators() } fun getAll(): Map<String, IValidator> = registered.toMap() }

这里有一个重要的实现细节:Kotlin 侧维护了一份mutableMapOf<String, IValidator>()影子注册表,clearAll()执行两步操作——

  1. registered.clear():清空 Kotlin 侧以IValidator实例形式保存的引用(释放 Kotlin 对象引用);
  2. XbergBridge.nativeClearValidators():调用 JNI 桥接方法,通知 Rust 原生层清空其全局注册表。

两步缺一不可:只清 Kotlin 侧会导致原生层仍持有已失效的验证器;只清原生层则 Kotlin 侧的IValidator引用会悬空。clearAll保证了两端一致性。

3.2 JNI 原生函数声明

nativeClearValidators在 XbergBridge.kt 中与另外两个验证器管理函数一起声明:

external fun nativeRegisterValidator(impl: io.xberg.ValidatorJniDispatcher) external fun nativeUnregisterValidator(name: String) external fun nativeClearValidators()

这三个函数一一对应 Rust 插件模块导出的三个注册表管理原语:register_validator、unregister_validator、clear_validators,后者统一从 plugins/mod.rs 导出。

3.3 Rust 侧实现:clear_validators

Rust 侧入口位于 plugins/validator/mod.rs:

/// Remove all registered validators. pub fn clear_validators() -> crate::Result<()> { use crate::plugins::registry::get_validator_registry; let registry = get_validator_registry(); let mut registry = registry.write(); registry.shutdown_all() }

实现要点:

  • 全局单例注册表:get_validator_registry()返回一个进程级的全局注册表,通过write()获取写锁,保证并发环境下清除操作的原子性;
  • 委托给shutdown_all():真正的清除逻辑在注册表内部完成(见下节);
  • 返回Result<()>:错误会沿 JNI 边界传回 Kotlin 侧,任何验证器 shutdown 失败都会导致调用抛错,而非静默吞掉。

四、底层注册表行为:shutdown_all 的语义

shutdown_all()是清除操作的真正执行者,实现在 registry/validator.rs:

/// Shutdown all validators and clear the registry. pub fn shutdown_all(&mut self) -> Result<()> { let names = self.list(); let count = names.len(); if count > 0 { tracing::debug!("Shutting down {} validators", count); } for name in names { self.remove(&name)?; } if count > 0 { tracing::debug!("Successfully shut down all {} validators", count); } Ok(()) } /// Drain the registry. Alias for `shutdown_all` used by alef trait-bridge codegen. pub fn clear(&mut self) -> Result<()> { self.shutdown_all() }

从源码可以归纳出几个关键行为:

  1. "清除"即"逐个 shutdown":shutdown_all并非简单清空一个集合,而是先list()出全部验证器名称,再逐个调用remove()。remove内部会对每个验证器调用其shutdown()方法(若失败会返回错误,并由上层记录 warn 日志),从而触发插件自身的资源释放逻辑;
  2. 空注册表是合法操作:count == 0时不进入循环、不打日志、直接返回Ok(())。这意味着对空注册表反复调用clearAll()是幂等且安全的——这也解释了 e2e 夹具为何能在任意状态下反复执行而不出错;
  3. clear()是shutdown_all()的别名:注册表同时提供clear()方法,供 alef trait-bridge 代码生成使用,保证各语言桥接层在命名上的一致性;
  4. 失败即中止:remove出错时会以?立即返回错误,剩余验证器不会被继续处理。调用方(即clear_validators)会把该错误沿 JNI 边界回传给 Kotlin 侧,最终体现为 Kotlin 调用抛出异常。

五、验证器注册表在测试中的行为印证

仓库在 registry/validator.rs 中提供了test_validator_registry_shutdown_all测试,直接验证shutdown_all的行为:

#[test] fn test_validator_registry_shutdown_all() { // ... 注册若干 MockValidator 后: registry.shutdown_all().unwrap(); // 断言 list() 结果为空 }

除此之外,plugins/validator/mod.rs中的单元测试还覆盖了验证器接口的完整契约,可作为理解"验证器被清空的对象是什么"的参考(见 plugins/validator/mod.rs):

  • Validatortrait 继承自Plugin,后者要求实现name()、version()、initialize()、shutdown();
  • Validator额外要求实现异步的validate(&ExtractedDocument, &ExtractionConfig) -> Result<()>;
  • 可选覆写should_validate()(按文档类型条件化校验)与priority()(默认 50,控制校验顺序)。

也就是说,clearAll()清空的是一组"持有校验规则并实现了插件生命周期"的对象,清除时触发的是它们的shutdown(),而不是简单的引用丢弃。

六、与相关插件注册表管理 API 的关系

clearAll在 xberg 插件管理体系中并非孤例,而是与验证器注册表管理 API 家族中的其他操作配套使用:

操作Kotlin 侧 API底层 Rust 函数语义
注册验证器ValidatorBridge.register(impl)register_validator注册并初始化一个验证器
按名注销ValidatorBridge.unregister(name)unregister_validator移除单个验证器并触发其 shutdown
列出全部Xberg.listValidators()list_validators返回当前注册的全部验证器名称
清空全部ValidatorBridge.clearAll()clear_validators逐个 shutdown 并清空注册表

类似的 clear 模式在仓库中其他插件注册表(OCR 后端、embeddings、reranker、post-processor、tokenizer、renderer、extractor)中均有对应实现,且都遵循"shutdown_all→clear别名 → alef trait-bridge 代码生成"的统一结构(可从 plugins/registry/validator.rs 与同目录下其他 registry 文件对比印证)。本片段的同目录文档(plugin_api 片段目录)中ocr_backends_clear.md、embedding_backends_clear.md、post_processors_clear.md、tokenizer_backends_clear.md等即为这些操作的 Kotlin (Android) 示例。

七、最佳实践与注意事项

  1. 清空后务必校验:夹具语义要求 "verify list is empty",生产代码中建议清空后调用Xberg.listValidators()断言列表为空,避免静默失败;
  2. 调用前持有注册表状态:ValidatorBridge.getAll()可获取清空前的全部验证器快照,如需在切换策略前备份旧规则,先getAll()再clearAll();
  3. 注意资源释放的异步性:验证器的shutdown()是同步调用,但validate()是异步的(async fn)。若在验证任务仍在飞行时调用clearAll(),需要自行保证任务已完成,否则可能出现"验证器已 shutdown 但任务还在跑"的竞态——这是应用层需要协调的时序问题;
  4. 错误处理:clearAll()返回Unit,但底层错误(如某个验证器 shutdown 失败)会作为异常沿 JNI 边界抛出,建议在调用点捕获异常并按需记录日志;
  5. 幂等性:对空注册表调用clearAll()是安全且幂等的,可在初始化、tearDown 中放心使用,无需先判断是否为空。

八、小结

ValidatorBridge.clearAll()虽然只是 Kotlin (Android) 平台上的一行调用,但其背后是一条完整且严谨的跨语言链路:Kotlin 侧影子注册表清理 + JNI 桥接 → Rust 侧clear_validators()获取全局注册表写锁 →shutdown_all()逐个触发验证器 shutdown 并清空注册表。这一设计保证了验证器在被移除前能够正确释放资源,同时通过Result错误传播让失败可见。配合Xberg.listValidators()即可完成"清空并验证为空"的完整闭环,是 xberg 插件生命周期管理中一个标准且安全的操作。

  • 后端
  • AI 应用
  • NLP

【免费下载链接】xberg

Polyglot document intelligence with a Rust core: extract text, metadata, images, tables, and structured data from 106 formats across 140 file extensions, plus code intelligence for 371 languages. Fifteen bindings, with CLI, REST API, and MCP server.

项目地址:https://gitcode.com/gh_mirrors/kr/xberg
点击查看免费下载
上一篇:Camel-5B与Llama的终极对比:技术架构、性能表现和应用场景深度分析
下一篇:ClearerVoice-Studio 完整上手攻略:AI 语音降噪、人声分离与音质增强一次搞定

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询