Deno Deploy EA でDB接続を試す

Deno Deploy EA で、データベースの接続を簡易にする方法が提供されるようになったようです。

これまで Deno Deploy からデータベース接続するには、個別のプロジェクトにそれぞれ環境変数を埋めるなど、面倒多いものでした。

やってみます。

参考

設定

現在Deno Deploy EAから接続が取れるのは、postgreSQL のみのため、今回はNeonを使い進める。

Deno Deploy 画面 Deno Deploy EAの画面にアクセスして、「Databases」を開く。

Deno Deploy 画面「Add Databases」を開く。

Neon 画面 Neonのプロジェクトで「Connnect」を開く。

Neon 画面 「Connection String」を控える。

Deno Deploy 画面 控えた文字列を「Connection String or Hostname」を貼り付ける。
貼り付けると、Credentioals が自動的に展開された。
Slug は、仮の名前として「testdb」を設定する。

設定完了すると、以下のように表示される。

実装

一旦PlayGround作成

接続の確認として、PlayGroundから接続する。

一旦PlayGroundを作成してデプロイ。

Database接続

Database接続の一覧から、「Assign」をクリックする。

Select App からPlayGroundを選択し、「Assign Database」をクリックする。

接続されたプロジェクトの名前が表示される。

続けて、PlayGround に以下のコードを追加する。
このコードは、Deno Deploy Early Access - Databases にあるサンプルを参考にしている。

1
2
3
4
5
6
7
8
9
10
11
import { Pool } from "npm:pg";

const pool = new Pool();

Deno.serve(async () => {
const result = await pool.query("SELECT * from products");

return new Response(JSON.stringify(result.rows), {
headers: { "content-type": "application/json" },
});
});

できたら右上の「Deploy」からデプロイする。

接続先にテーブルを作成していなかったので、上部の「Database」を開く。

「SQL console」から、テーブルを作る。
この操作はNeon側で実施してもよい。

続けて適当にデータを作る。

「Code」画面に戻り、再読み込みをすると、実行結果からデータベースにアクセスしていることがわかる。

「HTTP Explorer」から実行すると、より詳細の項目からリクエストを送れる。

とここまでの操作でPlayGroundとデータベースを1対1で接続できた。

何も設定してないのに接続できるのはなぜかという部分がある。
それは接続の設定により、アプリケーション割り当てた際に、環境変数が自動設定されるためだった。

Automatic Environment Variables Jump to heading

などが自動設定されるとのこと。

  • PGHOST
  • PGPORT
  • PGDATABASE
  • PGUSER
  • PGPASSWORD
  • PGSSLMODE

試しに以下の記述を追加してデプロイしてみる。

1
2
3
4
5
console.log(`PGPORT = ${Deno.env.get('PGPORT')}`)
console.log(`PGDATABASE = ${Deno.env.get('PGDATABASE')}`)
console.log(`PGUSER = ${Deno.env.get('PGUSER')}`)
console.log(`PGPASSWORD = ${Deno.env.get('PGPASSWORD')}`)
console.log(`PGSSLMODE = ${Deno.env.get('PGSSLMODE')}`)

実行すると上がってくるログは以下のようになった。

複数DB接続

公式のアナウンスでは、アプリケーションとデータべースの接続はn対1で可能と記されているので試してみる。

試しにもう1つのPlayGroundは、データを書き込むものにする。

1
2
3
4
5
6
7
8
9
10
11
import { Pool } from "npm:pg";

const pool = new Pool();

Deno.serve(async () => {
const result = await pool.query("INSERT INTO products (name) VALUES ($1)",[crypto.randomUUID()]);

return new Response(JSON.stringify({rowCount: result.rowCount}), {
headers: { "content-type": "application/json" },
});
});

デプロイしたら、先に紹介の方法で、もう1つ作ったPlayGroundにデータベースを割り当てる。
すると、2つ接続していることが確認できる。

はずだったが、登録したデータベースにアクセスできない。
その理由は、割り当て画面の記述にある。

You are about to attach the database instance testdb to the app fast-ferret-75.

Every timeline (Production, Git Branch / main, Git Branch / feat-1, etc.) will be provisioned an isolated database, with separate schema and data, within this database instance. This happens automatically when you deploy your app.

The production timeline (revisions on default branch) will use the database hogehoge-production
The Git Branch timelines (revisions on branches) will use the database hogehoge-{git.branch}
The Preview timelines (revisions for each commit) will all use the same database hogehoge-preview.
This is subject to change.

書いてあることとしては割り当てているプロジェクトごとに別のデータベースを作成すると述べられている。

先ほどの環境変数に割り当たっているものを確認するとことなっていることがわかる。

「複数のアプリから、同じデータベースを作成できる」という印象からは少し異なっていることが見えてくる。
どうやら同様のような質問は多いようで、回答も述べられている。

Frequently Asked Questions

プロジェクトの環境変数としてPGDATABASE を上書きすることを試したが解決できなかった。
以下のように、実装としてアプリケーション上で上書きしてから接続することで解決した。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { Pool } from "npm:pg";

// 環境変数を上書きする
Deno.env.set('PGDATABASE', Deno.env.get('PGDATABASE_OVERRIDE'))

const pool = new Pool();

Deno.serve(async () => {
const result = await pool.query("INSERT INTO products (name) VALUES ($1)",[crypto.randomUUID()]);

return new Response(JSON.stringify({rowCount: result.rowCount}), {
headers: { "content-type": "application/json" },
});
});

プロジェクトとして割り当てられているデータベースは変わっていないので、SQL console で見える先はそのまま。
なのでテーブルデータを直接見たい場合には、素直な紐づけをしているプロジェクトから行うとよい。

まとめ

Deno Deploy EA でデータベース接続を試してみた。
最初に受けていた印象とはいささか違いがあったが、複数のアプケーションからデータベースの接続を取ることができた。

少なくとも、個別に環境変数を埋め込まなくてよくなったのは利点。

その他見つけたのは、Deno Deployでは、環境変数はすべてsecretとして扱われるため、
動作確認の際に正しく設定されているかわかりにくかった。
EAではPlain Textとして設定もできるようになったので、これはありがたいポイントだった。

では。