本文へ移動
rdlabo.devdocs

ランタイム

Workerで nodejs_compat を有効にし、はじめにの依存を追加してください。mysql2 は含まれています。アプリがHyperdrive binding、スキーマ、ORMファクトリーを渡します。

呼び出し単位の寿命

createHyperdriveDatabase はモジュールのグローバル領域ではなく呼び出し内で作成します。接続は遅延生成され、そのDBインスタンスで再利用されます。ランタイムが呼び出し終了時に接続を片付け、互換用 dispose() は何もしません。

以下は1つのHyperdrive bindingを両方の役割に使うWorkerの例です。replicaがある場合は replicaHyperdrive に別のbindingを渡せます。

import { createHyperdriveDatabase, type HyperdriveLike } from '@rdlabo/workers-mysql';
import { DRIZZLE_ORM_OPTIONS } from '@rdlabo/workers-mysql/drizzle';
import { drizzle } from 'drizzle-orm/mysql2';

interface Env {
  DB: HyperdriveLike;
}

export default {
  async fetch(_request: Request, env: Env): Promise<Response> {
    const db = createHyperdriveDatabase({
      primaryHyperdrive: env.DB,
      replicaHyperdrive: env.DB,
      createOrm: (connection) => drizzle(connection, DRIZZLE_ORM_OPTIONS),
    });
    const rows = await db.query<Array<{ value: number }>>('SELECT ? AS value', [1]);
    return Response.json(rows);
  },
};

読み取りと書き込み

操作 接続先 結果の型引数
read<Row>(sql, params?) Replica 1行の型。戻り値は Row[]
query<Rows>(sql, params?) Primary SELECT Row[] など結果全体
readTransaction(fn) Primaryの一貫したスナップショット コールバック結果
write(fn) Primary ORM await済みコールバック結果
transaction(fn) Primaryトランザクション await済みコールバック結果

replicaの遅延を許容できない読み取りには query を使います。Hyperdriveのクエリキャッシュは別の設定事項です。SQL文字列への値の埋め込みではなくプレースホルダーを使ってください。

readTransaction は同じ読み取り専用スナップショットの { orm, query } を渡します。専用接続で直列実行されるため、コールバックから再帰呼び出ししないでください。

再試行の境界

DB操作はデッドロックを再試行します。コールバックから書き込みbuilderまたはPromiseをreturn/awaitしてください。トランザクション全体が再実行され得るため、メール・決済など外部の副作用は外に置きます。すでに再試行する操作をさらに retryWhenDeadlock で包まないでください。

HyperdriveのSELECTと読み取り専用トランザクションは、致命的な接続エラー時に新しい接続でさらに1回再実行できます。書き込み・書き込みトランザクションは接続切断で再実行しません。成否が不明な場合があるため、リクエストを再試行する前にアプリの冪等性を設計してください。

createMysqlDatabase({ orm, replica })databaseFrom(orm, replica) は既存ハンドルを包み、呼び出し元が接続を片付けます。追加のprimary読み取りメソッドを持つHyperdrive型ではなく Database を返します。Honoのcontainerにはkit 0.12.0 以降の @rdlabo/workers-hono-kit/mysql を使います。

接続の既定値はDrizzleと日付、exportはAPIを参照してください。