跳转到内容

输入关键词开始搜索文档。

Postgres

最后更新 查看 Markdown 源文件@flue/postgres

快速开始

使用 Postgres 蓝图为现有 Flue 项目添加持久化共享 Postgres 存储。在终端或你选择的编码智能体中运行以下命令:

flue add database postgres

概述

Postgres 蓝图会安装 @flue/postgres 并重用现有的 Postgres 驱动,或者默认添加 pg 和匹配的 @types/pg 开发依赖。它会在源代码根目录创建 db.ts,并在项目已有环境文档时更新它。默认生成的适配器使用连接池进行普通查询,并为每个事务保持在一个签出的连接上:

src/db.ts (简化版)
import { postgres } from '@flue/postgres';
import { Pool } from 'pg';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

export default postgres({
  query: async (text, params) => (await pool.query(text, params)).rows,
  transaction: async (fn) => {
    const client = await pool.connect();
    try {
      await client.query('BEGIN');
      const result = await fn({
        query: async (text, params) => (await client.query(text, params)).rows,
      });
      await client.query('COMMIT');
      return result;
    } catch (error) {
      await client.query('ROLLBACK');
      throw error;
    } finally {
      client.release();
    }
  },
  close: () => pool.end(),
});

Flue 在构建时发现适配器并将其连接到生成的 Node 服务器。启动时,它会创建或验证所需的 flue_* 表。规范的智能体对话、不可变附件和已接受的提交随后会在进程替换后得以保留。副本可以共享持久状态,但每个智能体实例仍然需要一个活动的 Node 所有者;Postgres 不启用主动 - 主动的同实例执行。应用业务数据仍由应用自行管理。此蓝图仅适用于 Node 目标,因为 Cloudflare 部署使用 Durable Object SQLite。

配置

变量用途
DATABASE_URL必需 — Postgres 连接字符串,例如 postgresql://user:pass@host:5432/db。

你的驱动在运行时读取 DATABASE_URL — 它不会被烘焙到构建中。对于本地开发,vite dev 会加载项目 .env 文件,而 flue run --env <file> 会选择替代的 .env 格式文件。在生产环境中,请从你平台的密钥存储中提供它。

蓝图默认使用 pg 安装 @flue/postgres,并在源代码根目录创建包装它的 db.ts。Flue 在构建时发现 db.ts 并将其连接到生成的 Node 服务器。运行命令后,规范的智能体对话、不可变附件和已接受的提交会持久化到 Postgres,而不是内存状态。

@flue/postgres 是一个 Node.js 适配器。Cloudflare 目标会自动使用 Durable Object SQLite,并在构建时拒绝 db.ts 文件,因此本指南适用于 Node 部署。有关每个目标如何存储状态的完整信息,请参阅数据库。

使用自定义驱动

@flue/postgres 不会选择或捆绑数据库驱动。它运行在你围绕已配置驱动包装的小型运行器上,因此你拥有驱动选择、连接池、TLS 和所有其他连接选项。运行器包含三个函数:query(带编号 $N 占位符的 SQL 字符串加上位置参数,返回结果行)、transaction(在一个连接上的一个事务中运行其回调)和 close。

使用 pg(node-postgres)时,transaction 会签出一个客户端并自行发出 BEGIN/COMMIT/ROLLBACK — 连接池无法跨任意连接运行事务:

src/db.ts
import { postgres } from '@flue/postgres';
import { Pool } from 'pg';

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

export default postgres({
  query: async (text, params) => (await pool.query(text, params)).rows,
  transaction: async (fn) => {
    const client = await pool.connect();
    // ...
  },
  close: () => pool.end(),
});

相同的接缝可以适配支持在一个连接上进行交互式事务的驱动。对于 Neon,请使用其 WebSocket Pool;HTTP 查询客户端无法实现此回调事务契约。

迁移

适配器的 migrate() 钩子会在生成的 Node 服务器启动时自动运行。它会幂等地创建 Flue 的 flue_* 表并标记格式版本,因此首次启动时会配置新数据库,重启时会重用现有数据库。没有单独的迁移命令需要运行,由较新 Flue 版本写入的数据库会拒绝启动,而不是损坏状态。

存储内容

Flue 数据库存储运行时状态,而不是整个应用。

由 Flue 存储:

  • 规范的智能体对话流和压缩记录;
  • 不可变附件负载;
  • 已接受的直接提示和 dispatch(...) 提交;
  • 持久化提交声明、租约和结算记录。

不由 Flue 存储:

  • 沙盒文件和已安装的依赖项;
  • 外部 API 副作用;
  • 应用拥有的业务数据,除非你自己的工具存储它;
  • 提供商凭证或密钥。

提交行是使已接受的工作在中断后可恢复的关键。有关恢复如何使用它们的信息,请参阅持久性, 有关确切适配器契约的信息,请参阅数据持久化 API。

何时选择 Postgres

用例适配器
本地开发,或不需要重启持久性来自 @flue/runtime/node 的 sqlite()(文件路径或内存)
单主机 Node 部署文件支持的 sqlite()
多副本 Node 部署,或状态必须在主机丢失后保留@flue/postgres,每个智能体实例一个活动所有者
Cloudflare 部署内置 Durable Object SQLite(无 db.ts)

当替换进程必须恢复已接受的工作时,当副本需要共享对话状态时,或者当单个主机的磁盘不是状态足够持久的存储位置时,请选择 Postgres。为每个智能体实例保留一个活动所有者,并在副本之间使用实例亲和路由。托管的 Postgres 与容器部署目标自然配对 — 有关 RDS 的信息,请参阅在 AWS 上部署, 有关在服务器旁边配置数据库的信息,请参阅其他部署指南。