实时数据
实时数据
这就是租户应用接触数据的方式。读取是 实时查询 ,写入是 乐观更新 ,两者都通过 $bolt/client ——你永远不需要打开连接、管理缓存或使任何东西失效。Bolt 的 同步引擎 让每个客户端保持最新;本页是该约定面向编写者的一半。
读取是实时查询
每次读取都是一个 实时查询 ,作为本地 SQL 针对数据的一份按策略过滤的副本执行。使用 client.db.<collection>.findMany 、 findFirst 或 count ——只由过滤、排序与限制构成的读取会经服务端所用的同一个编译器编译成本地 SQL,因此它即时完成且永不离开设备。关联展开、全文搜索、聚合与历史则交由服务器回答:一个仅仅接近的本地答案,比一个正确的远端答案更糟。当一条变更落地(无论是你的还是别人的),引擎会重新评估每个依赖该变更集合的实时查询,并把结果 diff 进响应式值。
import { client } from '$bolt/client';
const orders = client.db.orders.findMany({
where: { status: { eq: 'open' } },
with: { customer: true },
orderBy: { created_at: 'desc' }
});
// Live — another tab or automation closes an order and this result updates. 在这一切之前,副本只构建一次。它先依据租户自己的迁移完成置备,然后对该用户可读的每个集合做一次分页 快照 ,再从该快照交回的游标开始订阅流。仅靠变更日志无法做到这一点:只有经过集合运行时的写入才会进入 outbox,因此种子数据与导入的行完全不在其中。
写入是乐观更新
浏览器写入使用 client.db.<collection>.mutate(values) 。它返回 Promise<void>;成功完成会使受影响的实时查询失效。 client.db.<collection>.pending 是正在进行的数值计数,因此并发写入可以独立结束。
client.db.cost_estimates.mutate(values)
values = precisely typed root + any explicitly included relationship state
│ pending += 1
▼
server: policy → approvals → before hooks → reconcile the
root + every included relationship → after hooks → audit
│ (one transaction)
┌──────────┴───────────┐
▼ ▼
committed refused
affected queries reason surfaces;
invalidate nothing was written
│ │
└──────────┬──────────┘
▼ Promise<void> resolves; pending -= 1
affected live queries re-run and the outbox carries the
committed change to every other replica 已包含的关联表示其完整期望状态。其中的行会被插入或更新;以前已存储但未出现在其中的行会被删除。显式包含的关联会递归同步,而未包含的关联保持不变。根记录与所有已包含关联会原子协调。
生成的类型会精确描述该嵌套图,无需类型断言或兼容包装。查询拥有 current、loading 和 error;变更拥有 pending。组件不复制查询数据、刷新、加载、错误或变更状态。
import { client } from '$bolt/client';
await client.db.cost_estimates.mutate(values);
// The included relationship is its complete desired state. Present rows are
// inserted or updated; stored rows omitted from it are deleted. Relationships
// omitted from the mutation are untouched. Explicit nesting reconciles
// recursively, and the whole submitted graph commits atomically.
client.db.cost_estimates.pending; // numeric in-flight count mutate 从不返回记录:只写与行过滤策略可能允许写入,却不允许相应读取。实时查询是调用方可见数据的唯一来源。这个浏览器变更界面不定义顶层记录删除编码。
不变量
读取路径永远不会等待此设备已经见过的数据。 每个服务器应答都会折入本地副本——对任何内容的第二次访问都是即时的,应用代码中没有任何 invalidate 、 refetch 或 revalidate 。