好笑的是,雖然 using
語法來自 C# ,但用 Rust 的 lifetime 機制來解釋反而更清楚
- 至少一個有開啓 Replica Set 功能的 MongoDB instance
於 Docker 中搭建環境
本機須先安裝
mongosh
docker run -p 27017:27017 --name mongo --restart unless-stopped -d mongo mongod --replSet rs0
echo "rs.initiate({ _id: \"rs0\", members: [ { _id: 0, host: \"localhost:27017\" } ] })" | mongosh
- 專案 TypeScript 5.2 以上,並設置
tsconfig.json
如下
{
"compilerOptions": {
"target": "es2022",
"lib": [
"es2022",
"esnext.disposable",
"dom"
]
}
/* 其他原有的參數 */
}
- 安裝
core-js
npm i -D core-js
等這個 TC39 Proposal 過了之後,就不需要做這步了
import 'core-js/modules/esnext.symbol.async-dispose.js'; // 待 TC39 Proposal 通過後可移除
import 'core-js/modules/esnext.disposable-stack.constructor.js'; // 待 TC39 Proposal 通過後可移除
export class MongoTransaction implements AsyncDisposable {
session: any;
#abort: boolean = false;
constructor(session: any) {
this.session = session;
}
abort() {
this.#abort = true;
}
[Symbol.asyncDispose]() {
if (this.#abort) {
return this.session
.abortTransaction()
.finally(() => this.session.endSession());
} else {
return this.session
.commitTransaction()
.finally(() => this.session.endSession());
}
}
static async new(client: MongoClient) {
const session = await client.startSession();
session.startTransaction();
return new MongoTransaction(session);
}
}
Feathers 版(替換上方的
new
static method)static async new(app: Application) { const session = await app.get('mongoClient').startSession(); session.startTransaction(); return new MongoTransaction(session); }
await using transaction = await MongoTransaction.new(app);
try {
await db('database').collection('collection').insertOne({test: "test data"}, {session: transaction.session})
} catch (error) {
transaction.abort();
}
Feathers 版(替換上方的查詢)
await app.service('collection').Model.insertOne({test: "test data"}, {session: transaction.session})
- 利用
using
keyword new 一個新的MongoTransaction
class。 - 對資料庫進行操作:
在操作的後方加上{session: transaction.session}
,讓 MongoDB 使用開啓了 Transaction 的 Session 處理本次操作。 - 錯誤處理中,可以加上
abort()
method , 註記取消本次操作。
由於使用了 using
keyword ,JavaScript 會在 transaction
不再被用到時,自動執行 MongoTransaction
class 中的 [Symbol.asyncDispose]
。程式會根據是否註記取消操作,寫入資料庫後主動關閉連線,無需手動操作。