ADR-0053: DB の記事は PGlite を使い、Node のコードからは Unix ドメインソケットで pg から接続し、SQL は DB のプロセスの標準入出力で送る¶
Status¶
承認
Context¶
訪問者が Postgres の SQL を動かす形と、Node のコードから同じ DB に接続する形を決める必要がある。
記事には、pg のコードを、手元の Postgres に接続するときと同じ書き方で載せたい。
- DB を使う実行環境の選び方を決めた、有効な ADR は無い。
- ADR-0030: 種別を記事の 1 つにし、構成を記事の形式で、シリーズをディレクトリで表す
- DB の記事の主題は、Postgres のプランナの出力である。PGlite は、Postgres を WASM にしたもので、本物の Postgres と同じ
EXPLAIN ANALYZEを返す。cross-origin isolation を求めない。 - Node と npm の実行に WebContainers を採る。画面は、実行環境をインターフェースを通して使う。
- cross-origin isolation のヘッダは、Node の実行環境のパスと、それを埋め込む記事の URL にだけ返す。
- PGlite は、単一の接続で動く。
@electric-sql/pglite-socketは、PGlite を Postgres のワイヤプロトコルで待ち受け、複数の接続のクエリを 1 つずつ PGlite に渡す。- 出典: PGlite
- 出典: PGlite Socket
pgは、環境変数PGHOST、PGUSER、PGDATABASEを読む。PGHOSTが/で始まるときは、そのディレクトリの Unix ドメインソケットに接続する。- WebContainers の中の TCP のソケットでは、
pgからpglite-socketへの接続が失敗する。 - WebContainers の中では、Unix ドメインソケットの接続だけを持つ Node のプロセスが、クエリの結果を待たずに、終了コード 0 で終了することがある。エラーは出ない。
- 実行環境は、HTTP の流れを記録するために、Node のプロセスに preload を追加する。
- プレイグラウンドは、ツールごとにパスとページを分け、1 つのページに、複数のツールを置かない。
- 実行環境のモジュールは、プロセスの出力から、プレフィックスの付いた行を抜き出す。SQL だけを動かすツールは、
SqlDatabaseのインターフェースを持つ。 - プロジェクトの設定は、DB を使うかどうかと、初期データの SQL のファイルを持つ。
- 訪問者は、シェルを制限なしで使う。
- 実行環境が追加するファイルは、訪問者の作業ディレクトリの外に置く。preload は、
NODE_OPTIONSで渡す。 - AI のエージェントが書いたコードは、利用者が自分の操作で動かしたコードとして扱う。
Decision¶
1. SQL だけを動かす記事¶
SQL だけを動かす記事は、Node の実行環境を使わず、PGlite を単体で動かす。
- PGlite を動かすページは、プレイグラウンドのサブドメインの、isolation のヘッダを返さないパス(
/sql/)に置く。 - PGlite は、Web Worker で動かす。ツールのページのメインスレッドでは、SQL を実行しない。重いクエリの間も、画面の操作を受け付けるためである。
- Web Worker が異常終了したときは、SQL の画面にエラーを出す。次の実行で、Web Worker を作り直す。DB の中身は、初期の状態に戻る。
- PGlite で SQL を実行して結果の形にする関数、
SqlDatabaseの型、PGlite を Web Worker で動かすSqlDatabaseの実装は、package(@fukuemon/sql-runtime)に置く。DB のプロセスのスクリプトも、同じ関数を使う。 - PGlite は、利用者が実行のボタンを押したときのほかに、AI のエージェントが SQL を実行する操作を呼んだときにも読み込む。読み込んでから、操作を実行する。
- 操作が呼ばれるのは、利用者がスイッチをオンにし、自分のエージェントをつないだ後である。
- ADR-0045 の Decision 6 と同じく、エージェントの操作で読み込むことも、利用者の操作として扱う。
- SQL だけを動かす記事には、isolation のヘッダが適用されない。外部の画像と埋め込みを使える。
- 実行計画は、
EXPLAIN (ANALYZE, BUFFERS)のテキストと、FORMAT JSONの構造の両方を使える。
2. Node のコードから DB に接続する記事¶
Node のコードから DB に接続する記事は、実行環境の中の PGlite に、Unix ドメインソケットで接続する。
- 実行環境が、PGlite と
pglite-socketを持つ Node のプロセスを起動する。ソケットのパスは/tmp/.s.PGSQL.5432にし、maxConnectionsに 2 以上を渡す。 - このプロセスのファイルと依存(PGlite、
pglite-socket)は、訪問者の作業ディレクトリの外に置く(ADR-0052)。訪問者のファイルのツリー、作業ディレクトリ、package.jsonには出さない。 - 訪問者が、端末で
ls /tmpとpsを実行したときに、このプロセスとファイルが見えることは、受け入れる。 - DB を使うかどうかは、プロジェクトの設定で選ぶ。DB を使わないプロジェクトでは、このプロセスを起動しない。
- 実行環境は、起動のときに、プロジェクトの初期データの SQL を実行する。
- 実行環境は、訪問者のプロセスに、次の環境変数を渡す。
PGHOST=/tmp、PGUSER=postgres、PGDATABASE=postgresDATABASE_URL=postgres://postgres@%2Ftmp/postgres
- 記事のコードは、
new Pool()のように引数なしで書く形と、new Pool({ connectionString: process.env.DATABASE_URL })と書く形の、どちらも使える。 - TCP の
localhost:5432では待ち受けない。WebContainers の中の TCP のソケットでは、pgの接続が失敗するためである。 - 実行環境は、DB を使うプロジェクトで、訪問者のプロセスに、Unix ドメインソケットに接続している間はプロセスを終了させない preload を追加する。
- 訪問者が書いた短いスクリプトが、エラーなしでクエリの途中で終了しないようにするためである。
- 記事には、
node seed.jsのような短いスクリプトと、HTTP のサーバーのコードの、どちらも書ける。
Unix ドメインソケットを採る理由は、WebContainers の TCP の実装に依らずに pg の接続が通ることと、環境変数で接続先を渡す書き方が、本物のアプリの書き方と同じであることである。
3. SQL のペインと Node のコードが使う DB¶
DB を使うプロジェクトでは、Node の実行環境のページに、SQL を実行するペインを置く。
SQL のペインと Node のコードは、同じ DB(実行環境の中の PGlite)を使う。
訪問者が、SQL のペインで作ったテーブルを、Node のコードから読めるようにするためである。
- SQL のペインは、Node の実行環境というツールの一部として扱う。ADR-0031 の「1 つのページに、複数のツールを置かない」は、変えない。
- SQL の入力欄と、結果の表のコンポーネントは、SQL だけを動かすツールのページ(
/sql/)と共有する。
4. SQL を送る形式¶
SQL のペインは、DB のプロセスの標準入出力で SQL を送り、結果を受け取る。
標準入出力で送る理由は、プロセスもポートも増やさずに、Chromium、WebKit、Firefox で動くことである。
- リクエストは、1 行の JSON にする(
{"id": "<連番>", "sql": "<SQL>"})。 - レスポンスは、行頭に固定のプレフィックスを付けた、1 行の JSON にする。
- 成功のときは、
id、文ごとの結果の一覧、実行の時間を持つ。 - 失敗のときは、
id、エラー(メッセージ、SQLSTATE、位置)、実行の時間を持つ。 - 型は、プレイグラウンドの Design Doc にある。
- 成功のときは、
- プレフィックスの無い行(DB のプロセスのログと、入力のエコー)は、実行環境が捨てる。
- 複数の文を 1 回で送ったときは、最後の文の結果を表示する。1 つの文が失敗したときは、全部を取り消し、取り消したことをエラーの表示に書く。
- SQL だけを動かすツール(Web Worker で動かす PGlite)も、同じ
SqlResponseの形を返す。 - DB のプロセスの状態は、
SqlDatabaseのstatusで持ち、NodeRuntimeには持たせない。DB のプロセスが終了したときは、待っているリクエストにエラーを返し、SQL のペインにだけ、DB が止まったことをエラーとして出す。エラーの隣に、「実行環境を起動し直す」の操作を出す。起動し直した後は、再訪と同じに扱う。Node のコードと端末は、動かし続ける。
5. 結果の行の表示¶
SQL の結果は、100,000 行までを全て返し、ページ送りで見られるようにする。
- 1 ページの行の数は、訪問者が選ぶ。
- 1 つの結果が 100,000 行を超えるときは、先頭の 100,000 行だけを返し、全体の行の数と、切ったことを表示する。
- 100,000 行にする理由は、Chromium で、100,000 行の結果を受け取るのに 15 秒、300,000 行で 39 秒かかり、1,000,000 行は 120 秒で返らなかったためである。
- SQL だけを動かすツールも、同じ上限にする。
承認の条件¶
- 複数の文のうち 1 つが、実行のときのエラー(制約の違反など)で失敗したときに、全部が取り消されることを確認している。確認したのは、構文エラーの 1 件である。
- SQL だけを動かすツール(Web Worker で動かす PGlite)で、100,000 行の結果を返す時間を測っている。
@fukuemon/sql-runtimeの Web Worker の実装が、apps/playgroundの Vite のビルドで動くことを確認している。メインスレッドで PGlite を動かしたときの画面への影響は、測っていない。@fukuemon/node-runtimeが export する Vite の plugin で、DB のプロセスのスクリプトに関数を束ねられることを確認している。
Verification¶
WebContainers 1.6.4 の中の Node 24.22.2 で、次のパッケージを動かした。
- PGlite 0.5.16、
@electric-sql/pglite-socket0.2.19 pg8.16.3、postgres.js 3.4.7、pg-gateway0.3.0-beta.4
マシンは Apple M2、ブラウザは Playwright 1.65.0 の Chromium、WebKit、Firefox(headless)、配信は localhost である。
実機のブラウザは未確認である。
pg で接続できる方式¶
クライアントは、接続、select、パラメータ付きのクエリ、EXPLAIN (ANALYZE, BUFFERS)、begin と rollback を順に実行した。
クライアントのスクリプトは、25 秒で打ち切るタイマーを持つので、プロセスは、クエリの途中で終了しなかった。
| 方式 | サーバー | クライアント | 結果 |
|---|---|---|---|
| Unix ドメインソケット | pglite-socket |
pg(host: "/tmp") |
動く。1 つの接続、2 つの同時の接続、Pool |
| Unix ドメインソケット | pglite-socket |
pg(引数なし。PGHOST などの環境変数) |
動く |
| Unix ドメインソケット | pglite-socket |
pg(postgres://postgres@%2Ftmp/postgres) |
動く |
| Unix ドメインソケット | pglite-socket |
postgres.js(path) |
動く |
| TCP | pglite-socket |
pg |
動かない。invalid frontend message type 47 |
| TCP | pglite-socket |
postgres.js | 動かない。25 秒で打ち切り |
| TCP | 自前のブリッジ、pg-gateway |
pg、postgres.js |
動かない。25 秒で打ち切り |
TCP。net.Socket の write をラップする preload を、両方のプロセスに追加 |
pglite-socket |
pg |
動く。1 つの接続、2 つの同時の接続、Pool |
- Unix ドメインソケットと、preload を追加した TCP の行は、3 つのブラウザで同じ結果だった。preload なしの TCP の行は、Chromium で測った。
- WebContainers の中の TCP のソケットは、大きな
ArrayBufferの一部を指すBufferをwriteに渡すと、サーバーに 65536 バイトを届けた。届いたバイト列の途中に、クライアントが書いたバイト列が入っていた。pgとpglite-socketは、どちらもこの形のBufferを送る。 pglite-socketのmaxConnectionsのデフォルトは 1 で、2 つ目の同時の接続は切られる。- Unix ドメインソケットで、
pgの 1 回の実行(接続から切断まで)は、28〜54 ミリ秒だった。 - Prisma、Drizzle、Knex のような、
pgを中で使うライブラリは、試していない。
短いスクリプトの終了¶
Unix ドメインソケットの pglite-socket に、pg で接続する Node のコードを、次の表の形で実行した。
Pool と Client のスクリプトは、テーブルの作成、行の追加、行の数の select を順に実行し、end() を呼ぶ。
preload は、net.Socket の connect をラップし、パスを指定した接続が閉じるまで、setInterval のタイマーを動かす。
preload は、node -r で追加した。
| Node のコードの形 | Chromium | WebKit | Firefox |
|---|---|---|---|
new Pool() でクエリを 3 つ実行して終わるスクリプト |
1 つも終わらずに終了 | 最後まで実行 | 最後まで実行 |
new Client() で接続し、クエリを 3 つ実行して終わるスクリプト |
接続の後に終了 | 1 つ目のクエリの後に終了 | 最後まで実行 |
同じスクリプトで、setInterval のタイマーを動かしておく |
最後まで実行 | 最後まで実行 | 最後まで実行 |
| HTTP のサーバーが待ち受けているプロセスの中で、同じクエリを実行する | 最後まで実行 | 最後まで実行 | 最後まで実行 |
Pool と Client のスクリプトに、preload を追加する |
最後まで実行 | 最後まで実行 | 最後まで実行 |
- 途中で終了したプロセスの終了コードは 0 で、エラーは出なかった。
- preload を追加したスクリプトは、
end()の後に、終了コード 0 で終了した。 - 原因は、WebContainers の中の Unix ドメインソケットが、Node のイベントループを動かし続ける対象になっていないこととみられる。WebContainers の中の実装は、確認していない。
net.Socketのwriteをラップする preload を追加した TCP では、Clientのスクリプトは、3 つのブラウザで最後まで実行した。Poolのスクリプトは、行を入れた後、20 秒たっても終了しなかった。- preload を追加したプロセスで、接続を閉じないスクリプトが終了するかは、未確認である。
- この preload は、HTTP の流れを記録する preload と同じプロセスに追加しても動き、
NODE_OPTIONSで追加できた。結果は、ADR-0052 の Verification にある。
SQL を送る方法¶
実行環境の中で、1 つの Node のプロセスが、PGlite と、Unix ドメインソケットの pglite-socket を持つ。
ツールのページが、select、EXPLAIN (ANALYZE, BUFFERS)、Node のコードが入れた行の select を送り、結果を受け取るまでの時間を測った。
select と EXPLAIN は、5 回ずつ送った。
| 方法 | Chromium | WebKit | Firefox |
|---|---|---|---|
| DB のプロセスの標準入出力 | 動く。1〜5 ミリ秒 | 動く。1〜8 ミリ秒 | 動く。3〜23 ミリ秒 |
pg で接続したままの、別のプロセスの標準入出力 |
動く。1〜7 ミリ秒 | 動く。2〜11 ミリ秒 | 動く。4〜25 ミリ秒 |
SQL ごとに、pg で接続する Node のプロセスを起動する |
動く。255〜352 ミリ秒 | 動く。273〜326 ミリ秒 | 動く。313〜462 ミリ秒 |
ツールのページから、実行環境の中の HTTP のサーバーへ fetch する |
動かない | 動かない | 動かない |
実行環境の中の HTTP のサーバーが返すページを iframe で開き、postMessage で頼む |
動く。6〜12 ミリ秒 | 動く。7〜14 ミリ秒 | 動かない |
- DB のプロセスの標準入出力では、ツールのページが、プロセスの入力に 1 行の JSON を書き、出力から同じ id の行を読んだ。
- 動いた方法の全てで、
EXPLAIN (ANALYZE, BUFFERS)の 10 行を受け取れた。cost、actual time、Buffers:、Planning Time、Execution Timeを含む。 - 動いた方法の全てで、Node のコードが
pgで入れた行を、ツールのページで読めた。ツールのページから入れた行を、Node のコードがpgで読めた。 fetchは、ブラウザが CORS で止めた。サーバーのコードはAccess-Control-Allow-Origin: *を返すが、Chromium のコンソールには、このヘッダがレスポンスに無いというエラーが出た。- iframe のページは、Firefox で読み込まれなかった。
大きな SQL と、大きな結果¶
DB のプロセスの標準入力に、1 行の JSON で SQL を書き、応答の行を読むまでの時間を測った。DB のプロセスは、PGlite の exec で実行した。
| SQL | サイズ | Chromium | WebKit | Firefox |
|---|---|---|---|---|
insert を 300 個と select を 1 個 |
14.5 KB | 18 ミリ秒 | 19 ミリ秒 | 14 ミリ秒 |
insert を 3000 個と select を 1 個 |
153 KB | 117 ミリ秒 | 80 ミリ秒 | 63 ミリ秒 |
1 MB の文字列リテラルを持つ select を 1 個 |
1 MB | 72 ミリ秒 | 27 ミリ秒 | 57 ミリ秒 |
- DB のプロセスが受け取ったバイト数は、送ったバイト数と同じだった。
- 150 行目に構文エラーがある 300 行の SQL を送ると、エラーが返った。エラーの前の 149 個の
insertは、入っていなかった。 - プロセスの出力には、ツールのページが標準入力に書いた行が、そのまま出た。
5 つのカラム(整数、文字列、整数、32 文字の文字列、時刻)を持つ行を、generate_series で作って select し、応答の行を読むまでの時間を測った。
| 行の数 | 応答の行のサイズ | Chromium | WebKit | Firefox |
|---|---|---|---|---|
| 1,000 | 0.12 MB | 0.14 秒 | 0.02 秒 | 0.03 秒 |
| 10,000 | 1.2 MB | 1.3 秒 | 0.13 秒 | 0.33 秒 |
| 100,000 | 12.5 MB | 15.0 秒 | 1.2 秒 | 3.2 秒 |
| 300,000 | 37.8 MB | 38.6 秒 | 4.0 秒 | 9.2 秒 |
| 1,000,000 | 126.7 MB | 120 秒で返らない | 14.9 秒 | 32.5 秒 |
- 時間の大半は、DB のプロセスの中の、クエリの実行と JSON への変換だった。ツールのページの
JSON.parseは、1,000,000 行で 0.24〜0.30 秒だった。 - ツールのページのメモリの使用量と、100,000 行を表に描く時間は、測っていない。
- SQL だけを動かすツール(Web Worker で動かす PGlite)で、同じ行の数を返す時間は、測っていない。
DB のプロセスのファイルの置き場¶
DB のプロセスのスクリプトを /tmp の下のディレクトリに置き、依存を npm install --prefix <そのディレクトリ> で入れた。3 つのブラウザで同じ結果だった。
- DB のプロセスが起動し、訪問者のプロセスから
pgで接続できた。 - 訪問者の
package.jsonとnode_modulesに、PGlite とpglite-socketは入らなかった。作業ディレクトリのls -aに、DB のプロセスのファイルは出なかった。 ls -a /tmpには、ディレクトリと.s.PGSQL.5432が出た。psには、DB のプロセスがnodeとして出た。- 依存の
npm install(9 つのパッケージ)は、3.1〜4.5 秒だった。
Considered Options¶
| 選択肢 | 強み | 弱み |
|---|---|---|
| 採用: Unix ドメインソケットで待ち受け、環境変数で接続先を渡す。接続している間はプロセスを終了させない preload を、訪問者のプロセスに追加する | WebContainers の TCP の実装に依らない。記事のコードが、環境変数で接続する本物のアプリと同じ書き方になる。短いスクリプトも、HTTP のサーバーのコードも書ける | host: "localhost" と port: 5432 を書いたコードは動かない。接続先が Unix ドメインソケットであることを、記事で説明する。preload が、Node の net.Socket の connect をラップする |
| Unix ドメインソケットで待ち受け、preload を追加しない。DB に接続するコードは、HTTP のサーバーの中で DB を使う形に限る | Node に手を加えない | 記事に、node seed.js のような短いスクリプトを書けない。訪問者が自分で書いたスクリプトが、エラーなしで途中で終了する |
TCP で待ち受け、net.Socket の write をラップする preload を、全てのプロセスに追加する |
記事のコードが、接続先の書き方まで手元と同じになる | preload が、DB のプロセスと訪問者のプロセスの両方に要る。Pool を使う短いスクリプトが、20 秒たっても終了しなかった。WebContainers の中の動きに依る。HTTP のサーバーと、HTTP の記録の preload への影響を確認していない |
| Unix ドメインソケットと、preload を追加した TCP の両方で待ち受ける | どちらの書き方も動く | 2 つの方式を保守する。preload の弱みを、そのまま持つ |
| 実行環境の中の PGlite を、HTTP で使う | 追加の仕組みが少ない | 記事のコードが、pg と違う書き方になる |
| SQL の画面と Node のコードが、別の DB を使う | SQL の画面が、どの記事でも、SQL だけを動かすツールと同じく、Web Worker で動かす PGlite で動く。実行環境へ SQL を送る仕組みが要らない | 訪問者が SQL の画面で作ったテーブルを、Node のコードから読めない |
SQL のペインを置く場所の選択肢は次のとおり。
| 選択肢 | 強み | 弱み |
|---|---|---|
| 採用: Node の実行環境のページに、SQL のペインを置く | 訪問者が、同じ画面で、SQL と Node のコードを行き来できる。トップレベルで開いたページでも使える | Node の実行環境のページのペインが増える |
記事に、Node の実行環境の iframe と、SQL のツールの iframe を並べ、記事のページが postMessage で中継する |
ページとツールが、1 対 1 のままになる | 記事のページに、中継のスクリプトが要る。トップレベルで開いたときに、SQL を送れない |
DB のプロセスとファイルを、訪問者から隠す範囲の選択肢は次のとおり。
| 選択肢 | 強み | 弱み |
|---|---|---|
採用: ファイルのツリー、作業ディレクトリ、package.json に出さない。ls /tmp と ps に出ることは、受け入れる |
訪問者のプロジェクトに、実行環境のファイルが入らない。訪問者は、シェルを制限なしで使える | 訪問者が、DB のプロセスを kill で止められる |
シェルに、ps と /tmp を隠す手段を探す |
訪問者から、プロセスとファイルが見えない | WebContainers のシェルに、その手段があるかは未確認である。node -e で /tmp を読める |
| シェルを出さない | 訪問者から、プロセスとファイルが見えない | 訪問者が、自分でコマンドを試せない |
実行環境の中の PGlite へ SQL を送る方法の選択肢は次のとおり。
| 選択肢 | 強み | 弱み |
|---|---|---|
| 採用: DB のプロセスの標準入出力 | プロセスが増えない。ポートを使わない。3 つのブラウザで動く | DB のプロセスの標準出力に、SQL のペインへの応答の行が流れる |
pg で接続したままの、別のプロセスの標準入出力 |
SQL のペインも、Node のコードと同じ pg の接続で DB を使う |
プロセスが 1 つ増える |
SQL ごとに、pg で接続する Node のプロセスを起動する |
常に動くプロセスが増えない | 1 回の実行が 255〜462 ミリ秒かかる |
実行環境の中の HTTP のサーバーが返すページを iframe で開き、postMessage で頼む |
標準入出力を使わない | Firefox で動かない。ポートを 1 つ使い、訪問者のプレビューの一覧に出る |
標準入出力で送る形式の選択肢は次のとおり。
| 選択肢 | 強み | 弱み |
|---|---|---|
| 採用: リクエストもレスポンスも 1 行の JSON にし、レスポンスにプレフィックスを付ける | 1 MB の SQL まで動いた。SQL の中の改行は、JSON のエスケープで 1 行に収まる。エコーの行を捨てられる | DB のプロセスのログが、プレフィックスで始まる行を出すと、レスポンスとして読む |
| 長さを先頭に書くフレームにする | 本体に何が入っていても区切れる | プロセスの出力は、ログも流れるテキストのストリームで、フレームの途中にログが入ると読めない |
| SQL と結果を、実行環境のファイルに書いて渡す | 出力のストリームに、ほかの行が入らない | ファイルの監視が要る。1 回にかかる時間は、測っていない |
結果の行の表示の選択肢は次のとおり。
| 選択肢 | 強み | 弱み |
|---|---|---|
| 採用: 全ての行を返し、ページ送りで見せる。100,000 行を超える結果だけを切る | 訪問者が、結果の全体を見られる。大きすぎる結果で、ブラウザが長く待たない | 100,000 行に近い結果は、Chromium で 15 秒かかる |
| 1000 行で切る | 応答が速い | 訪問者が、1001 行目から後を見られない |
| 上限を置かない | 切る処理が無い | Chromium で、1,000,000 行の結果が 120 秒で返らない |
| ページごとに、DB のプロセスに問い合わせる | 1 回の応答が小さい | ページを送るたびに、SQL を実行し直す。副作用のある SQL と、結果が変わる SQL を扱えない |
PGlite を読み込む時期の選択肢は次のとおり。
| 選択肢 | 強み | 弱み |
|---|---|---|
| 採用: 実行のボタンを押したときのほかに、AI のエージェントが SQL を実行する操作を呼んだときにも読み込む | 利用者は、エージェントをつないだ後に、実行のボタンを押さなくても、エージェントに実行させられる | スイッチがオンの間は、利用者が実行のボタンを押していなくても、エージェントの操作で読み込む |
| PGlite を読み込んでいないときは、AI のエージェントからの操作が失敗を返す | 読み込む時期が、実行のボタンを押したときの 1 つで済む | 利用者が、先に実行のボタンを押すことになる |
Consequences¶
Positive¶
- 訪問者は、記事の
pgのコードを、手元のアプリにそのまま持ち出せる。 - 訪問者は、SQL のペインで実行計画を読みながら、同じ DB を Node のコードから使える。
- 利用者は、エージェントをつないだ後に、実行のボタンを押さなくても、エージェントに SQL を実行させられる。
- SQL だけを動かす記事は、WebContainers のライセンスとブラウザの対応に依らずに公開できる。
- 訪問者が書いた短いスクリプトは、クエリを最後まで実行してから終了する。
- SQL のペインのために、実行環境の中のプロセスとポートが増えない。
Negative¶
localhost:5432に接続するコードは、実行環境の中で動かない。- Node のコードから DB に接続する記事は、PGlite と
pglite-socketを npm で入れる転送量が増え、起動に 3.1〜4.5 秒が加わる。 - DB を動かす形が 2 つになり、初期データを入れる処理と、SQL を送る先を、2 つの形で持つ。
- 実行環境が訪問者のプロセスに追加する preload が、HTTP の流れを記録するものと合わせて 2 種類になる。接続している間はプロセスを終了させない preload は Node の
net.Socketのconnectをラップするので、Node と WebContainers のバージョンを上げるときに、短いスクリプトの動きを確認し直す。 - DB のプロセスの標準出力に、SQL のペインへの応答の行が流れる。実行環境は、応答の行と、DB のプロセスのログを、プレフィックスで区別して読む。
- 訪問者が、端末で
psとls /tmpを実行すると、DB のプロセスとファイルが見える。訪問者は、DB のプロセスをkillで止められる。止めた後は、「実行環境を起動し直す」まで、SQL のペインと、Node のコードからの接続が使えない。 - 100,000 行を超える結果は、先頭の 100,000 行だけを見られる。
- 複数の文を 1 回で送り、1 つが失敗すると、成功した文も取り消される。
- スイッチがオンの間は、利用者が実行のボタンを押していなくても、エージェントの操作で、PGlite を読み込む。