[storage] Drive 对象无法在组件启动初期通过 db:select() 查询到吗?

我在 storage app 的 init() 方法末尾,启动了如图所示的协程,循环从数据库中查询 Drive 记录的数量

我可以确保,Drive 对应的数据库中,有正确的持久化记录,非空

但是,storage 模块在刚启动时查到的 Drive 持久化记录数为0

(可以看到上面的打印,persist client init 早就 completed 了,但是为什么还是查不到呢?)

大约 10 秒后,Drive 才能被 select 出来

问题:为什么会这样,数据库里明明有 Drive 的数据,为何查询不出来,这里面是何种机制?

尝试了在启动时查询同为远程持久化的 GlobalStorageConfigTable ,它的内容是可以正常查询出来的,所以应该不会是 init 阶段太早导致的(理论上在 ctor 之后应该就能用远程持久化了);

所以为什么 Drive 在这段时间查询不到呢?是因为和 orm object 有耦合的原因吗?

答案内容由AI生成,仅供参考:
根据您提供的上下文信息,我们可以系统性地分析为什么 Drive 对象在组件启动初期无法通过 db:select() 查询到,尽管数据库文件中已存在持久化数据。


:white_check_mark: 核心结论(直接回答您的问题)

Drive 对象在组件启动初期查询不到,是因为其 ORM 对象尚未被完整加载到内存中,而 self.db.Drive 是一个 ORM 映射对象,依赖于 Resource Tree 和 Object Manager 的初始化完成。数据库虽有数据,但 ORM 层未建立对象映射,导致查询返回空。


:books: 详细机制分析(基于上下文)

1. self.db.Drive 是 ORM 映射对象,不是直接的数据库表

  • 从上下文可知,db 是一个 ORM 数据库接口对象,其方法如 select, where, all() 都是通过 ORM 框架 实现的。
  • self.db.Drive 并非直接访问 SQLite 表 t_storage_drive,而是访问一个 由 ORM 框架管理的内存对象模型
  • 只有当 ORM 对象被正确初始化并注册到 Resource Tree 后,self.db.Drive 才能关联到持久化数据。

:white_check_mark: 参考 :

  • ORM FrameworkResource Tree 关联:“ORM is initialized during the resource tree construction to finalize object state and associations.”
  • ORM Framework 使用 c_object_manage 管理对象生命周期。

2. 组件启动流程存在明确的阶段依赖

从您的日志可以看出,组件启动分为以下关键阶段:

时间戳 事件 说明
10:59:59.453 Startup status: Starting ==> InitCompleted 组件初始化完成(init() 执行)
10:59:59.727 DEBUG Drive count = 0 您的协程首次查询,返回 0
11:00:02.198 start to fetch hwdiscovry objects 硬件发现开始,开始构建 Resource Tree
11:00:09.561 add objects completely, path: /bmc/kepler/ObjectGroup/... ORM 对象加载完成,此时 Drive 才被注入内存
11:00:09.585 DEBUG Drive count = 18 首次成功查询到数据

:warning: 关键点:您在 init() 中启动的协程,运行在“组件初始化完成”阶段,但此时 ORM 对象尚未从持久化数据库加载到内存中。

3. 为什么 GlobalStorageConfigTable 能查到,而 Drive 不能?

  • GlobalStorageConfigTable 可能是 在组件初始化时通过预置或静态注册 加载的 ORM 对象。
  • Drive动态发现对象,需要通过:
    1. 硬件发现(hw discovery)
    2. Resource Tree 构建
    3. Object Manager 注册对象
    4. ORM 框架绑定数据库映射
    5. 最终才能通过 self.db.Drive 查询

这说明:Drive 是一个“由硬件发现触发、动态创建”的 ORM 对象,而不是在组件启动时就静态加载的。

4. 为什么不能在 init() 里直接查?

  • init() 是组件的“初始化阶段”,但 ORM 对象的持久化数据加载发生在“对象管理器完成资源树构建之后”
  • 在此之前,self.db.Drive 虽然存在(Lua 表已定义),但其底层映射的数据库记录尚未被加载到内存中。
  • 所以 db:select().all() 返回的是 空集合,不是数据库无数据,而是 ORM 层未激活

:white_check_mark: 类比:就像你打开了一个数据库连接,但还没执行 SELECT * FROM table —— 但这里更严重:连表的“对象模型”都没注册好

5. 为什么延迟 10 秒后能查到?

  • 日志显示:11:00:02.198 开始 fetch hwdiscovry objects11:00:09.561 完成对象添加。
  • 这 7 秒正是 硬件发现、对象创建、Resource Tree 构建、ORM 映射绑定 的完整周期。
  • 只有在 add objects completely 之后,self.db.Drive 才真正“感知”到数据库中的记录。

:pushpin: 补充:为什么不能用 pcall 包裹解决?

  • 您的查询不是“失败”,而是返回空
  • pcall 只能捕获错误(error),不能解决“数据未加载”的逻辑时序问题。
  • 从上下文看:“组件初始化过程中的数据库操作必须在 pcall 中调用”(ID:3),但这适用于可能抛异常的写操作(如 db:insert),不适用于读操作的时序依赖

:white_check_mark: 总结:根本原因

问题 原因
为什么 Drive 查询不到? self.db.Drive 是 ORM 映射对象,依赖硬件发现和 Resource Tree 构建完成,才能从数据库加载数据到内存。
为什么 GlobalStorageConfigTable 能查到? 它是静态注册对象,在组件初始化阶段已由框架预加载,不依赖硬件发现。
为什么 10 秒后能查到? 因为此时硬件发现完成,c_object_manage 已完成对象注册,ORM 映射生效。
如何修复? 监听 object_manage 的对象加载完成事件,再启动查询。

:end_arrow: 最终建议

不要假设“组件初始化完成”=“所有 ORM 对象可用”。
在 BMC/ORM 架构中,对象的生命周期是由 Resource Tree 和 Object Manager 驱动的,而非组件的 init() 函数。