この記事の概要
Node.js CLIプログラム 開発中に遭遇した問題とその対応内容を記録する。
DBレイヤーに使用した Prisma と SQLite3 の組み合わせで発生。
開発元のIssuesでは、ざっくり昨年10月頃以降に同様の項目がある。
ワークアラウンドは判ったが、現時点までに本質的な修正はないように見えた。
何が起きた?
よくわからないが、処理がエラーで中断する。
コンソールのメッセージを頼りに、調査した。
エラー発生時のコンソール出力(抜粋)
PrismaClientUnknownRequestError:
Invalid `prisma.images.update()` invocation:
Error occurred during query execution:
ConnectorError(ConnectorError { user_facing_error: None, kind: ConnectionError(Timed out during query execution.) })
clientVersion: '4.6.1'
}
ここでimagesは、テーブル名。簡単に言うと、SQLクエリーがタイムアウトにより失敗したということ。
実行時の環境
- @prisma/client@4.6.1
- prisma@4.6.1
- Node.js v18.10.0
- Ubuntu 22.10
- sqlite3(cli) 3.37.2 2022-01-06 13:25:41
Issues
PrismaClientとSQLite3の組み合わせに限って起きている。
現時点で最新のバージョンにて発生している。
「CLIプログラム」だけに限るわけでもない。
いくつか、Promise.allでSQLクエリを並列していると起こるなどといったことが書かれているが、実際にはこれに限らない。
とにかくSQLへのクエリが一定以上に重複すると起きるようだが、閾値など詳しい条件は(私は)調べていない。
解決方法 ソース
Issueのひとつにあったワークアラウンド(以下に示す)では、コネクションプールを減らすことで解決できたとのこと。
要点の抜粋
adding ?connection_limit=1 to the connection string ...
さて「?connection_limit=1」は、どこに書くのか?
以下で順に追っていく。
(Sample) ./prisma/schema.prisma
DB接続文字列なので、まずschema.prismaを確認する。
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
→.envを調べよう
(Sample) ./.env
結論としては、このファイルに書く。
↓変更後。
DATABASE_URL="file:./dev.db?connection_limit=1"
Model
(参考)
Prismaからのコンソール出力を設定している。
以下に Model の冒頭を抜粋。
import { PrismaClient, Prisma } from '@prisma/client';
// (snip)
export default class Model {
constructor() {
this.prisma = new PrismaClient({
log: ['info', 'warn', 'error'],
});
}
// (snip)
}
再試行
解決策を導入したあとに、試行したときのコンソール出力を見ると、prisma:info Starting a sqlite pool with 1 connections.
とある。
コネクションプールが1本になっているように見える。
デフォルトは、ホストの『CPUスレッド数+1』
発生時のような処理の中断は回避できている。
ただし開発途中のため、本件と関係ない別の問題がまだあるが、ここでは省略する。
おわりに
これにて本件の問題を解決したので、記事を締めとする。