跳至主要內容

Cloudflare D1 儲存

Cloudflare D1 儲存實作使用 Cloudflare D1 提供 serverless SQL 資料庫方案,支援關聯式操作及交易一致性。

不支援可觀測性

Cloudflare D1 儲存不支援 observability domain。來自 MastraStorageExporter 的 Trace 無法持久保存至 D1,而當 D1 是你唯一的 storage provider 時,Studio 的可觀測性功能亦無法運作。如要啟用可觀測性,請使用複合儲存,將可觀測性資料路由至 ClickHouse 等受支援的 Provider。

資料列大小限制

Cloudflare D1 強制實施 1 MiB 的資料列大小上限。儲存包含圖片等 base64 編碼附件的訊息時,可能會超出此限制。請參閱處理大型附件,了解包括將附件上載至外部儲存空間在內的解決方法。

安裝
安裝 的直接連結

npm install @mastra/cloudflare-d1@latest

用法
用法 的直接連結

配合 Mastra CloudflareDeployer 使用
配合 Mastra CloudflareDeployer 使用 的直接連結

在 Cloudflare 上配合 Mastra 使用 D1Store 的標準方式,是使用 CloudflareDeployer。從 cloudflare:workers 匯入 env,並在 new Mastra({...}) 內以 inline 方式初始化 D1Store

src/mastra/index.ts
import { env } from 'cloudflare:workers'
import { D1Store } from '@mastra/cloudflare-d1'
import { Mastra } from '@mastra/core'
import { CloudflareDeployer } from '@mastra/deployer-cloudflare'

export const mastra = new Mastra({
storage: new D1Store({ binding: env.DB }),
deployer: new CloudflareDeployer({
name: 'my-worker',
d1_databases: [
{
binding: 'DB',
database_name: 'your-database-name',
database_id: 'your-database-id',
},
],
}),
})
備註

使用 import { env } from 'cloudflare:workers' 時,必須在 new Mastra({...}) 內以 inline 方式初始化 D1Store,不可將其抽取為 module-level 變數。另一做法是在 env 可用後,於 fetch handler 內初始化 D1Store。詳情請參閱 CloudflareDeployer 參考

在沒有 HTTP 路由的 Cloudflare Worker 中使用
在沒有 HTTP 路由的 Cloudflare Worker 中使用 的直接連結

如要直接在 Worker 中呼叫 Mastra(例如執行 Agent 或觸發 Workflow),而不提供 HTTP 路由,便不需要 CloudflareDeployer。從 Worker 的 env 參數存取 D1 binding,然後以程式方式呼叫 Mastra。

import { D1Store } from '@mastra/cloudflare-d1'
import { Mastra } from '@mastra/core'

type Env = {
DB: D1Database
}

export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const mastra = new Mastra({
storage: new D1Store({ binding: env.DB }),
})

const agent = mastra.getAgent('my-agent')
const result = await agent.generate('Hello')

return Response.json({ text: result.text })
},
}

配合 REST API 使用
配合 REST API 使用 的直接連結

在非 Workers 環境(Node.js、serverless function 等)中,請使用 REST API 方式:

import { D1Store } from '@mastra/cloudflare-d1'

const storage = new D1Store({
accountId: process.env.CLOUDFLARE_ACCOUNT_ID!, // Cloudflare Account ID
databaseId: process.env.CLOUDFLARE_D1_DATABASE_ID!, // D1 Database ID
apiToken: process.env.CLOUDFLARE_API_TOKEN!, // Cloudflare API Token
tablePrefix: 'dev_', // Optional: isolate tables per environment
})

Wrangler 設定
Wrangler 設定 的直接連結

將 D1 資料庫 binding 加至你的 wrangler.toml

[[d1_databases]]
binding = "DB"
database_name = "your-database-name"
database_id = "your-database-id"

或在 wrangler.jsonc 中設定:

{
"d1_databases": [
{
"binding": "DB",
"database_name": "your-database-name",
"database_id": "your-database-id",
},
],
}

參數
參數 的直接連結

binding?:

D1Database
Cloudflare D1 Workers binding(用於 Workers runtime)

accountId?:

string
Cloudflare Account ID(用於 REST API)

databaseId?:

string
Cloudflare D1 Database ID(用於 REST API)

apiToken?:

string
Cloudflare API Token(用於 REST API)

tablePrefix?:

string
所有資料表名稱的可選前綴(適合用作環境隔離)

補充說明
補充說明 的直接連結

Schema 管理
Schema 管理 的直接連結

儲存實作會自動處理 schema 建立及更新,並建立以下資料表:

  • threads:儲存對話 thread
  • messages:儲存個別訊息
  • metadata:儲存 thread 及訊息的額外 metadata

初始化
初始化 的直接連結

將 storage 傳入 Mastra class 時,系統會在任何儲存操作前自動呼叫 init()

import { Mastra } from '@mastra/core'
import { D1Store } from '@mastra/cloudflare-d1'

type Env = {
DB: D1Database
}

// In a Cloudflare Worker
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const storage = new D1Store({
binding: env.DB,
})

const mastra = new Mastra({
storage, // init() is called automatically
})

// Your handler logic here
return new Response('Success')
},
}

如直接使用 storage 而不配合 Mastra,則必須明確呼叫 init() 來建立資料表:

import { D1Store } from '@mastra/cloudflare-d1'

type Env = {
DB: D1Database
}

// In a Cloudflare Worker
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const storage = new D1Store({
id: 'd1-storage',
binding: env.DB,
})

// Required when using storage directly
await storage.init()

// Access domain-specific stores via getStore()
const memoryStore = await storage.getStore('memory')
const thread = await memoryStore?.getThreadById({ threadId: '...' })

return new Response('Success')
},
}
注意

如未呼叫 init(),資料表便不會建立,而儲存操作會在沒有提示的情況下失敗或拋出錯誤。

交易及一致性
交易及一致性 的直接連結

Cloudflare D1 為單一資料列操作提供交易保證。多項操作可以作為單一、全有或全無的工作單元執行。

建立資料表及 migration
建立資料表及 migration 的直接連結

初始化 storage 時會自動建立資料表(亦可使用 tablePrefix 選項按環境隔離),但進階 schema 變更需要手動 migration 及仔細規劃。例如加入欄位,或變更資料類型及 index,以免資料遺失。