ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Beads 存储层扩展契约:深入解析 `IssueFilter.Lite` 轻量 SELECT 与部分水合机制

Beads 存储层扩展契约:深入解析 `IssueFilter.Lite` 轻量 SELECT 与部分水合机制 Beads 存储层扩展契约深入解析IssueFilter.Lite轻量 SELECT 与部分水合机制【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads本文围绕 Beads 仓库内部存储扩展文档 engdocs/EXTENDING.md 展开系统讲解嵌入或直连 bd 存储层的调用方必须遵守的IssueFilter.Lite契约哪些重 TEXT 列会被省略、返回的*types.Issue上哪些字段可信、如何用IsLitePartial感知水合深度以及这一机制在issueops存储栈中的强制点与后端覆盖边界。读完本文你将能安全地在自己的调用方代码中启用 lite 扫描并理解其与完整水合路径、模式 Bid 收缩与 counts 大查询之间的协作关系。这份文档的定位存储 API 调用方契约engdocs/EXTENDING.md开篇即明确自己的读者群体它不是面向终端用户的文档而是面向嵌入 bd 或直接对话存储层的代码。凡是调用store.SearchIssues(ctx, query, filter)的模块都受这份契约约束。这意味着文中描述的IssueFilter.Lite是一个内部扩展点——它不会改变bdCLI 的默认行为而是为那些希望跳过大型正文列、只做路由/列表类读取的调用方提供一条显式可选的快路径。文档中出现的工程标识如 be-uwvs.2说明这是有计划的演进lite 契约本身已经落地在 issueops 栈而把filter.Lite贯通到 domain/db 代理服务器栈被明确推迟到后续的 CLI 接线工作中。为什么需要 Liteheavy TEXT 列的成本bd 的issues表把一张 issue 的所有内容都放在同一行里其中包含六个体量可观、以自由文本为主的 TEXT 列description描述design设计acceptance_criteria验收标准notes备注waiters等待者列表payload事件载荷这六列就是源码中 internal/storage/issueops/scan.go 定义的HeavyDropList。对一个以“列出所有 issue 供路由决策”为目的的查询来说这六列中的绝大多数内容根本不会被读取路由只需要身份、状态、优先级、时间戳、标签、依赖这些“小而常读”的列。把多 KB 的正文列随每一行一起物化是对 IO 与内存的浪费。IssueFilter.Lite正是为此设计当filter.Lite true时存储层发出一个更窄的 SELECT从投影列中剔除上述六个重列让列表路径只搬运真正需要的数据。调用方契约三条 MUST/MAY 规则engdocs/EXTENDING.md以非常明确的措辞规定了 lite 结果的语义任何调用方都必须遵守MUST NOT禁止读取被省略的六个字段当以IssueFilter.Lite true调用store.SearchIssues时调用方绝对不得从返回的*types.Issue上读取Description、Design、AcceptanceCriteria、Notes、Payload或Waiters。lite 扫描之后这些字段全部是零值——它们根本没有从行中取回读取它们不产生任何信号。把“零值”误当成“内容为空”是这类 API 最常见的错误用法。MAY可以读取其余所有字段除上述六个字段外其余字段在 lite 扫描中全部保留身份标识ID、标题、内容哈希、状态、优先级、类型、时间戳创建/更新/开始/关闭/截止/推迟、标签、依赖、元数据metadata、租约覆盖列lease_expires_at、heartbeat_at、granted_node、行版本令牌row_lock与存储类storage_class。源码中 internal/storage/issueops/scan.go 的 lite 目标列表证实了这一点——它只跳过了HeavyDropList中的六列。值得注意的是metadata被刻意保留。scan.go 的注释明确说明它“体积小且路由会读取”row_lock与租约三列也保留因为它们是乐观并发令牌、活跃租约状态与授权副本标识属于路由/认领代码的必读项而非本次拆分要跳过的多 KB 正文。MUST用IsLitePartial检测部分水合如果调用方需要针对水合深度做分支处理必须通过issue.IsLitePartial来检测 lite 抓取的记录。该字段在 internal/types/types.go 中定义是仅内部可见的标志json:-永远不会随序列化跨过线路wire——也就是说任何外部消费者都无法通过 JSON 观察到它这使它成为区分“真·无文本 issue”和“未水合的文本”的唯一内部手段。恢复完整正文的唯一途径GetIssuelite 列表之后如果针对某个特定 issue 需要完整正文唯一正确的恢复方式是调用store.GetIssue(ctx, id)——它始终返回完整行。internal/storage/issueops/get_issue.go 的实现印证了这一点它固定使用完整的IssueSelectColumns投影配合LeaseJoin与单行扫描。默认行为零成本迁移IssueFilter.Lite默认值为false见 internal/types/types.go 的字段注释。因此所有未显式选择加入的现有调用点保持今天的行为六个重列完整水合Issue.IsLitePartial为false。这是一个向后完全兼容的开关——新增该字段不会让任何存量代码悄悄改变语义只有显式设置Lite: true的调用方才会进入窄投影路径。这一设计在 internal/storage/issueops/search.go 中体现得极为直白func SearchIssuesInTx(ctx context.Context, tx DBTX, query string, filter types.IssueFilter) ([]*types.Issue, error) { proj : issueProjection if filter.Lite { proj issueLiteProjection } return searchInTx(ctx, tx, query, filter, proj) }filter.Lite只在两个投影字面量之间做一次选择其余全部共享。契约在源码中的强制位置engdocs/EXTENDING.md精确列出了四处强制点逐一对应到源码列清单scan.go的三个常量internal/storage/issueops/scan.go 定义IssueSelectColumns完整水合的规范列清单直接复用sqlbuild.IssueSelectColumnsIssueSelectColumnsLitelite 列清单与完整清单保持列顺序一致仅剔除HeavyDropListHeavyDropList被省略的六个重列注释明确要求其满足集合恒等式cols(IssueSelectColumnsLite) ∪ HeavyDropList cols(IssueSelectColumns)。扫描助手ScanIssueFrom与ScanIssueLiteFrom同一文件中的两个扫描函数按位置positionally绑定扫描目标二者都必须与各自的列清单逐列对应ScanIssueFromscan.go水合全部字段IsLitePartial保持falseScanIssueLiteFromscan.go不读取六个重字段并在返回前设置issue.IsLitePartial true第 414 行。注意 scan.go 第 68-69 行的警告调用方必须保证查询精确选择了IssueSelectColumns或 Lite 版且顺序一致位置扫描对列顺序极度敏感——这正是下面 schema-parity 守卫要锁死的东西。SELECT 分发search.go的投影选择internal/storage/issueops/search.go 定义了两个searchProjection[*types.Issue]字面量issueProjection完整列 ScanIssueFromissueLiteProjectionlite 列 ScanIssueLiteFrom注释明确指向 engdocs/EXTENDING.md 作为调用方契约。两者共享同一套 wisp-merge 与水合机制searchTableInTxT标签/依赖水合hydrateIssueLabelsAndDeps、issueswisps 双平面合并、去重GH#3567、LeaseJoin租约连接、Pattern B id 收缩全部由searchProjection[T]泛型抽象承载lite 投影不另起炉灶。Schema 一致性守卫scan_test.go的两个测试这是把契约“焊死”在 CI 上的关键TestIssueSelectColumns_LitePlusHeavyEqualsFull集合守卫。未来任何列被加入IssueSelectColumns而未归类到IssueSelectColumnsLite或HeavyDropList二者之一测试即失败并给出可操作的错误信息TestIssueSelectColumnsLite_IsFullMinusHeavyInOrder顺序守卫。集合比较无法发现“两个同类型列被对调”的问题——因为扫描是位置绑定列对调后每行的值会静默错位而没有任何成员关系变化。该测试以“从完整清单原位删除重列必须精确复现 lite 清单”为 oracle把 lite 清单变成完整清单的派生结果而非第二份手工维护的副本防止“新列加到完整清单中间却追加到 lite 清单末尾”的漂移。配套行为测试同样完备TestScanIssueLiteFrom_LeavesHeavyFieldsBlank 验证六字段零值、身份字段仍水合、IsLitePartialtrueTestScanIssueFrom_PopulatesHeavyFields 验证其反面search_lite_merge_test.go 则从端到端确认Lite: true确实触发了 lite 扫描路径。源码级原理投影抽象、租约覆盖与共享的列构建器searchProjection[T]一次抽象三种投影internal/storage/issueops/search.go 的searchProjection[T]结构体把“投影列 → 扫描函数 → ID 提取 → 后扫描水合 → Go 侧排序 → 租约连接”全部参数化。三种投影实例各司其职投影列扫描用途issueProjectionIssueSelectColumnsScanIssueFrom完整水合issueLiteProjectionIssueSelectColumnsLiteScanIssueLiteFromlite 窄投影idProjection仅id裸 ID 扫描模式 B 收缩 / 部分 ID 解析模式 BidShrink值得一提对带Limit的宽投影查询先跑廉价的SELECT id扫描再对幸存行批量抓取并水合避免为被 LIMIT 丢弃的行流式搬运整个投影。lite 投影与完整投影一样启用idShrink说明 lite 与 Pattern B 是正交的两层优化前者削减每行的宽度后者削减行数。列清单的真正宿主sqlbuild纯 SQL 构建器列清单的实际定义不在 issueops而在 internal/storage/sqlbuild/sqlbuild.goIssueBaseColumns第 46-55 行与IssueBaseColumnsLite第 64-73 行行本身的列不含租约覆盖LeaseSelectColumns第 79 行与LeaseJoin第 99-101 行租约覆盖列与LEFT JOIN leases ON leases.issue_id table.id片段IssueSelectColumns/IssueSelectColumnsLite第 86-93 行基础列 租约覆盖列的组合。sqlbuild包被经典 issueops 栈生产*sql.Tx与 domain/db 仓库栈代理服务器共享其设计目标是保证两个实现针对相同过滤器产生相同的行集合由 Seam A 奇偶校验套件固定。任何选用IssueSelectColumnsLite的查询都必须同时在 FROM 子句中包含LeaseJoin(table)——漏掉连接会在leases.*引用上响亮失败而不会静默出错。counts 大查询中的 Lite 变体lite 契约不止作用于无计数搜索。按 internal/types/types.go 的注释filter.Lite在两个栈上都被计入返回IssueWithCounts的计数页读取bd list --json的两条路由与GET /v0/beads/issues它作为sqlbuild.CountsHydration.Lite搭乘 counts 大查询而 internal/storage/sqlbuild/counts.go 中渲染的就是基础列的带限定符变体如ReadyWorkIssueColumns。后端覆盖与已知边界engdocs/EXTENDING.md的最后一部分交代了诚实的能力边界这对调用方至关重要已支持filter.Lite目前仅由 issueops 支撑的存储后端Dolt、嵌入式 Dolt通过上述分发机制执行尚未支持代理服务器路径 internal/storage/domain/dbissueSQLRepositoryImpl.searchTable/fetchIssuesByIDs尚不检查filter.Lite总是发出完整的issueSelectColumns查询并返回完全水合的 issueIsLitePartial false定性文档将其明确评价为“正确但未优化”correct-but-unoptimized——由于目前尚不存在 lite 调用方这一差异在今天就不可见把filter.Lite贯通 domain/db 栈的工作被推迟到 CLI 接线后续be-uwvs.2不属于本次基础工作的一部分。这意味着如果你的调用方运行在 proxied-server/domain/db 路径上设置Lite: true目前不会报错也不会加速——你得到的是行为正确但完全水合的结果。这是可观测、可预期的降级而不是契约违反。这一事实边界也提醒嵌入式集成者判断某个查询是否真正走了 lite 路径唯一可靠的方法是检查返回行的IsLitePartial是否为true而不是假设设置即生效。实践要点速查为嵌入式调用方库用户、扩展、自定义路由总结安全用法列表/路由类读取设置filter.Lite true只消费身份、状态、优先级、时间戳、标签、依赖与元数据字段绝不读取Description/Design/AcceptanceCriteria/Notes/Payload/Waiters——它们是零值不构成“内容为空”的证据需要分支用issue.IsLitePartial判断水合深度该标志不会出现在任何序列化输出上需要正文对单个 issue 调用store.GetIssue(ctx, id)恢复完整行验证生效检查IsLitePartial true若在 domain/db 代理路径上观察到false属于文档明确记载的“正确但未优化”状态做后端选型确认目标存储是 issueops 支撑的 Dolt/嵌入式 Dolt 后端否则 lite 暂不生效。延伸阅读契约正文engdocs/EXTENDING.md列清单与扫描实现internal/storage/issueops/scan.go投影分发与共享机制internal/storage/issueops/search.go纯 SQL 列构建器internal/storage/sqlbuild/sqlbuild.goIsLitePartial与IssueFilter.Lite定义internal/types/types.goSchema 一致性守卫internal/storage/issueops/scan_test.go读取器契约含 lite 断言backend/conformance/reader_contract.go【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表