SuperAPI AI 工具集

db-core/custom-adapter

数据与分析

查看项目

更新于 10-16 09:42

技能介绍

用途

本技能建立在 db-core 和 db-core/collection-setup 之上,用于为新的后端编写自定义集合适配器。适配器通过 sync() 函数接入 TanStack DB 集合,使后端数据能够同步进集合,并支持写入回传后端。

主要能力

  • SyncConfig 接口:sync 函数接收 begin、write、commit、markReady、markError、truncate 等回调;每次调用 sync() 都会启动一次同步运行(sync run),该运行拥有自己的回调与资源,直到其返回的 cleanup 结束为止。
  • 初次同步与实时订阅:先订阅实时事件,再拉取初始数据;拉取期间缓冲事件,初始同步完成后再重放,避免丢失变更。
  • ChangeMessage 格式:insert、update(部分或整行替换,配合 rowUpdateMode: "full")、delete 三种写入形式。
  • On-demand 同步(loadSubset):sync() 返回 SyncConfigRes,其中可包含 loadSubset;loadSubset 必须通过 begin() → write() → commit() 写入获取的行并 resolve void(或返回 true 表示立即同步结果),并不直接返回数据行。parseLoadSubsetOptions() 只返回 filters、sorts、limit;offset 和 cursor 需从原始 options 读取。cursor 是查询表达式(whereFrom、whereCurrent),需要为你的 API 翻译或组合。仅当 loadSubset 创建持续资源(如按子集的服务器订阅)时才返回 unloadSubset。
  • 乐观状态持续时间:变更处理程序必须等到服务器变更同步回集合后才 resolve。五种策略:Refetch(await collection.utils.refetch())、事务 ID(返回 { txid } 并通过 sync 流跟踪)、基于 ID 的跟踪(等待特定记录 ID 出现在 sync 流)、版本/时间戳(等待 sync 流追平变更时间)、提供方方法(await backend.waitForPendingWrites())。
  • 持久化同步元数据:metadata API 可存储跨同步事务持久化的按行与按集合元数据,用于记录恢复令牌、游标、LSN 等状态。metadata 对象与 begin、write、commit 一同出现在 sync 配置参数中;其公共类型是可选的,严格 TypeScript 需要做保护或断言。无持久化时元数据仅在内存中,不会跨重载存活。
  • 谓词下推的表达式解析:parseWhereExpression、parseOrderByExpression、extractSimpleComparisons 可用于 loadSubset 或 queryFn,把条件与排序转换为后端可用的比较表达式。

常见错误

  • CRITICAL 在 sync() 旁边定义 loadSubset:错误写法是把 loadSubset 作为 sync 配置的兄弟属性;正确做法是从 sync() 返回 { loadSubset, cleanup },并用同步事务原语写入已加载的行。
  • CRITICAL 未调用 markReady():不调用 markReady() 集合不会进入 ready 状态,实时查询永不 resolve,useLiveSuspenseQuery 会永久挂起在 Suspense。若初始同步在产生可用快照前失败,应调用 markError(error)。
  • HIGH 竞态:在初始拉取后再订阅:必须在拉取初始数据前订阅实时事件,拉取期间缓冲事件,初始同步完成后再重放。
  • HIGH 未调用 begin() 就调用 write():同步数据必须在事务内写入(begin → write → commit),否则抛出 NoPendingSyncTransactionWriteError。
  • HIGH 对已有同步键插入不同值:仅当值未变时,对已有同步键的 insert 才会被规范化为 update;值不同会抛出 DuplicateKeySyncError。应发出 update,或先 delete/truncate 旧行再插入新行。

限制与张力

入门级的简单用法(localOnly、eager 模式)与生产环境的正确性(on-demand 同步、竞态预防、正确的 markReady 处理)之间存在张力;追求快速搭建的代理往往会跳过缓冲、markReady 和清理函数。