SuperAPI AI 工具集

neon-realtime

数据与分析

查看项目

更新于 10-16 14:51

技能介绍

Neon Realtime 让任意 SQL 查询“活”起来,可在 Lakebase Postgres 上构建具备端到端反应式能力的应用与智能体,支持类型安全的活查询与乐观写入。使用前建议先参考父级 neon 技能了解 Neon 概览、入门与开发最佳实践;若未安装,可从 https://neon.com/docs/ai/skills/neon/SKILL.md 获取,或运行 neon skills -s neon -y 安装。Realtime 较新且处于 beta,其 API 不在训练数据中,需要从核心模式入手,并在编写相应代码前阅读对应章节的参考文件。

用途

  • 将应用中原本通过 API 或其它同步系统获取的数据,替换为由活查询驱动的实时数据。应复用现有查询代码,并尽量使用最贴合需求的最高层封装,而不是手工把变更接入应用状态。

主要能力与分层结构

  • Realtime 由多层组合而成:Postgres 内部的活查询引擎、Live SQL API(WebSocket API)、更低层的客户端 SDK(seal()、subscribe()),以及 useLiveQuery 等反应式原语。
  • 在可信后端代码中定义活查询(任意只读 SQL,包括 join、聚合、排序与 limit),用 NEON_REALTIME_SECRET 封装(seal),并通过需鉴权的端点或 server function 暴露。客户端无法读取或更改已封装查询的 SQL 与参数。
  • 客户端用已封装查询进行订阅:先收到完整初始结果,随后每个已提交事务的变更作为一个批次送达。结果保持一致,但不保证每个变更事件都被送达。
  • 写入通过你自己的 API 完成,写入会返回 txid,供 awaitTxId() 使用。

使用方式(栈选择)

  • 使用 Drizzle 或 Kysely 编写查询时,可用 @neon/realtime-drizzle 的 drizzleAdapter(),或 @neon/realtime-kysely 的 kyselyAdapter()。
  • 使用其它 ORM 或不用 ORM 时,可用 @neon/realtime/server 的 rawSql。
  • React 中可用 @neon/realtime-react 的 useLiveQuery,把一个已封装查询绑定到组件状态。
  • 需要在同一数据上做多个视图,或使用 TanStack DB 时,可用 @neon/realtime-tanstack 的 realtimeCollectionOptions:先把一个更宽的查询过度同步(oversync)进 collection,再从中派生本地活查询。
  • 其它框架可用 @neon/realtime/client 的 client.subscribe()。
  • 智能体与 worker 在可信后端代码中可用 @neon/realtime/server 的 realtime.subscribe()。
  • 从 Electric 迁移:Realtime 可作为 Electric 在栈中角色的直接替代,活 SQL 查询取代 shapes,realtimeCollectionOptions() 取代 electricCollectionOptions()。

设置

  • 新应用:neon bootstrap my-app --template realtime-react,然后在 my-app 中运行 neon deploy。
  • 在关联分支上启用:neon realtime enable --allowed-origin <app origin>,或在 neon.ts 中声明 preview: { realtime: true }(neon config add realtime)后运行 neon deploy。子分支会继承该设置。在 Claimable 项目被认领前,或在支持区域之外不可用。
  • 表需要有稳定的副本标识(replica identity),主键即可。
  • 环境变量:neon env pull --service postgres --service realtime 会写出 DATABASE_URL、NEON_REALTIME_URL 和 NEON_REALTIME_SECRET。仅把 URL 以框架的公开前缀(如 VITE_)暴露给浏览器。url 选项使用 NEON_REALTIME_URL;db 使用来自 DATABASE_URL 的数据库名。
  • 安装 @neon/realtime 及所选包。请使用这些 SDK,而非仍在演进的 WebSocket 协议。

定义与封装查询

  • 编写查询或封装代码(包括 Kysely 与 server function)前,阅读 references/queries.md。
  • 查询须只读且确定性。原始查询是单个 SELECT,不含分号,使用 $1 占位符。不能调用 now() 或 gen_random_uuid(),这类值应作参数传入;除字符串、数字、布尔、bigint 和 null 外的值都要用 pgParam 帮助函数包裹(如 pgParam.timestamptz(date))。
  • 在查询中做授权:封装前检查会话,并通过成员关系表 join,使被撤销的访问自动排除。任何 Web 框架鉴权都可用,包括 Managed Better Auth,但目前不支持 RLS。
  • 已封装查询是 bearer token,勿置于 URL、日志或持久化存储中,切勿用未校验输入填充其参数。
  • 接入前可先验证查询:neon realtime subscribe "SELECT ..." 会打印初始结果,随后打印每个事务的变更,直到手动停止;配合 --output json 时每个变更打印完整快照。可在 createRealtime 上设置 debugMode 获取完整数据库错误(仅开发环境)。
  • 已封装查询会过期。向绑定传入 refreshQuery,或调用 renew(),用相同查询与参数重新封装,否则订阅报错。新参数需要新的已封装查询与订阅。Next.js 中应从 Route Handler 执行 renew,因为 server action 一次只运行一个。

订阅

  • 编写 React 或 TanStack DB 代码前阅读 references/reactivity.md。直接用 client.subscribe(sealed)(getSnapshot、onChange、onStateChange)订阅前阅读 references/subscribing.md;从智能体与 worker 订阅时,在 createRealtime 中加入 url,并 await realtime.subscribe(query) 以在进程内封装。
  • 每个客户端对应一个数据库:首个已封装查询会把连接绑定到其 db。
  • 为每一行选择稳定且唯一的 key 并按它索引行,包括 TanStack DB 的 getKey:通常用主键、聚合的分组列,或 join 中重复行所组合的 key。切勿使用 rowId,它会在每次行更新时失效。
  • error 是最终态,即使 renew() 之后也是。应获取新的已封装查询并重新订阅,若连接失败则使用新 client。直接订阅时关注 onStateChange;useLiveQuery() 通过 status 报告错误,而非抛出或挂起。
  • 会话变化时以整页加载离开,以丢弃 Realtime client、任何 TanStack DbClient 及前一用户的行。hook 会每秒重试失败的续期,因此一旦某次续期失败即视为已登出并停止续期。每次续期都要检查,并确认会话用户与页面加载时的用户一致,否则旧页面的写入会落到新用户账户。

乐观写入

  • Realtime 没有写入路径,写入沿用后端常规鉴权。编写变更前阅读 references/mutations.md。
  • 从写入本身返回 txid:.returning({ txid: sql<string>pg_current_xact_id()::text }),在任何 Postgres 驱动上都是一次往返。把一批写入放在一条语句中,从而只有一个 txid。切勿仅为 select pg_current_xact_id() 而开 db.transaction()。当写入确实需要多条语句时,把 txid 放在总会改动某行的写入的 RETURNING 中。
  • 始终给 awaitTxId() 传超时:它会跨重连与续期持续等待,若 txid 未到达该查询则永不落定。
  • 不改变任何行的写入没有 txid,应跳过 awaitTxId(),让乐观状态自然消失。

服务端渲染

  • 在服务端渲染活查询(Next.js、TanStack Start)前阅读 references/ssr.md。
  • 在 useState 初始化器中创建 client,而非模块级;把 initialData 作为活行渲染,不设 loading 状态;切勿在请求间共享 TanStack DbClient。
  • 两侧保持行结构一致。JSON.stringify 会把日期变成字符串,int8 与 numeric 会以字符串形式到达。

更多文档(任务与页面)

  • Beta 范围、区域、定价、FAQ、其它系统:Overview
  • 架构与一致性:How it works
  • 第一个活查询:Quickstart
  • 每个 SDK 导出:TypeScript SDK reference
  • 带鉴权与 SSR 的全栈应用:Next.js、TanStack
  • 活智能体工作流:Mastra
  • ORM 适配器:Drizzle、Kysely

限制

  • 功能处于 beta;具体区域、定价与其它系统支持情况见 Overview 文档。
  • 在 Claimable 项目被认领前或支持区域之外不可用。
  • 目前不支持 RLS。
  • 不保证每个变更事件都被送达。
  • 已封装查询会过期,需续期。