はじめに
トランザクション内で処理を行いたいとき、BEGINして~クエリ書いて~COMMITして~エラーならROLLBACKして~を毎回書くのは大変ですし、抜け漏れが発生する恐れがあるので、メソッドとして共通化してしまうことにしました。
環境としては、Node.jsからpgモジュールを使用して、Linuxサーバ上のPostgreSQLへの接続となります。
ちなみに前回までの記事はこちらになるので、参考にしてみてください。
LinuxサーバーにPostgreSQL導入~外部サーバー接続まで
Node.jsからPostgreSQLへコネクションプールを使った接続
実際のコード
pool.js
const { Pool } = require("pg");
// 接続先文字列
const connectionString = 'postgres://user:pass@DBのアドレス:ポート/DB名';
// DB情報をもったプールを生成
const pool = new Pool({
connectionString: connectionString,
max: 2 // 保持するコネクション数
});
pool.tx = async (cb) => {
const connection = await pool.connect();
let res;
try {
await connection.query('BEGIN');
try{
res = await cb(connection);
await connection.query('COMMIT');
} catch(err) {
await connection.query('ROLLBACK');
throw err;
}
} catch(err) {
throw err;
} finally {
connection.release();
}
return res;
}
module.exports = pool;
index.js
const express = require('express');
const app = express();
const pool = require('./pool.js');
app.get('/', async function(req, res, next) {
let result;
try {
result = await pool.tx(async client => {
const res1 = await client.query('SELECT NOW()'); // ➀
const res2 = await client.query('SELECT NOW()'); // ➁
const res3 = await client.query('SELECT NOW()'); // ➂
return res1;
});
} catch(err) {
console.error(err);
res.sendStatus(500);
return;
}
res.status(200).json({data: result.rows})
});
app.listen(3001, () => console.log(`listening on port 3001!`));
コールバック関数内に複数のクエリを書くことで、それらが1つのトランザクション内のクエリとなります。
上のソース内で言うと➀➁➂が1つのトランザクション内にまとまるということです。
最後に
pg-promiseモジュールだとtxっていうメソッドで、たしか勝手にトランザクション管理してくれるんですよね。
そのうち、pgとpg-promiseの違いについてもまとめてみようと思います。
(ほかにもpg-poolとかあるっぽいので、できればそれも…)