实时数据
实时数据
读取有两种模式,按名称选择:await q 读取一次,bolt.live(q) 只要仍有内容在渲染它就保持实时。宿主保存每个实时视图的当前结果,并把每次提交对它造成的变更推送过来,因此页面从不轮询,也不需要在自己写入后重新获取。
实时读取
<script lang="ts">
// src/data/collection/projects/+representation.svelte (templates/construction, excerpt)
import { bolt, live } from '$bolt';
import type { RecordView } from '@norbital-ai/ui';
let { view }: { view: RecordView<'projects'> } = $props();
const record = $derived(view.mode !== 'create' ? view.record : null);
const sites = live(
() =>
record === null ? null :
bolt.live(bolt.read('site_locations', {
where: { project_id: { eq: record.id } },
select: { location_name: true, location_code: true, location_type: true },
orderBy: { location_name: 'asc' },
all: true
}))
);
</script> bolt.live(q) 订阅该查询。只要有读取方在渲染,订阅就持续存在,最后一个读取方离开后还有 30 秒宽限期。提到 now 或 today 的查询必须用 every 说明多久重新计算一次。
一次性读取
// src/kiosk/attendance/+clock.page.svelte (templates/hr-payroll, excerpt): an event's one-shot read
import { Effect } from 'effect';
import { bolt, fork } from '$bolt';
function loadHolders() {
fork(bolt.read('employment_profile', {
where: { face_enrollment_status: { eq: 'APPROVED' } },
select: { name: true, face_embedding: true },
all: true
}).pipe(Effect.tap((answer) => Effect.sync(() => { holders = [...answer.rows]; }))),
(error) => { message = error.message; });
} 游标分页与相似度搜索只能一次性读取。页面启动时或点击后需要的值用 await;屏幕上其他人可能更改的内容用实时读取。
乐观写入
通过 bolt.act 进行的 create、update 或 delete——以及每次 Form 保存、Table 编辑与 Board 移动——都会立即在它影响的实时读取上绘制变更,并按结果落定:committed 用已提交的行替换绘制内容,pendingApproval 将行保留为挂起状态,refused 或 conflict 撤回绘制并返回消息。操作与查询不会进行绘制。
更新会携带页面最后读取到的行修订号;如果该行此后已被更改,结果就是 conflict。进行中的写入只由 await 决定先后顺序。
读到自己的写入
当 act 完成时,页面的实时视图已经包含这次写入:回复中带有该提交的序号,客户端会等待(至多 5 秒,且仅在流打开时)直到它的流已应用该提交。
实时读取能看到什么
实时视图按查看者当前的授权与字段遮罩计算。查看者权限变化时,受影响的视图会重新给出结果;发布版本变化时,流会关闭,页面随之载入新版本。同步引擎指南说明了宿主如何路由每次提交。