我在大量Nodejs開發實踐中,發現回滾是一個非常嚴謹的話題,我們應該重視這個回滾話題。我們不能祈禱上天程式不要出錯,而忽略掉錯誤處理方案。
比如,我們在開發一個釋出系統的過程中,有一系列的操作,資料庫CRUD,FS操作專案檔案,同時對gitlab的api進行操作。這個時候我們的順序可能是這樣的:
- 資料庫插入一個專案並且返回一個專案ID
- 使用這個專案ID,通過FS操作,命名這個專案的資料夾為
project_${id}
- 將這個專案資料夾及一下所有的檔案上傳到一個FTP去
- 然後在gitlab中操作這個專案相關詳情
我們來腦補下場景:
- 如果我們在第1步就出錯了,資料庫插入就出現問題,可能我們資料庫突然掛掉,那麼程式就會丟擲錯誤,當然沒關係,因為後續操作沒有進行。
- 如果我們在第2步出現錯誤,這個資料夾是重名的,那麼可能會丟擲錯誤了,但是當時我們沒有使用回滾,導致資料庫已經插入,但是資料夾內容與我們想要的不匹配。
- 如果我們在第3步出錯了,資料庫已經插入,資料夾已命名,FTP突然掛掉,那麼資料庫出現了無效資料,檔案也出現了無效資料。
- 如果我們在第4步出錯了,其他都正確,那麼我們是否因為前3步出現的操作,導致資料無法同步,檔案無法同步,api操作無法同步
那麼我們就多麼尷尬啊。當然,我們可以通過捕獲錯誤來進行相對應的錯誤處理。但是我們不知道我們會在哪一步出現而回滾對應的行為。經過我的總結,提出3種回滾模式:
- 事務回滾 (mysql, redis, mssql等)
- 物理回滾 (主要是fs操作等)
- api回滾
我們需要建立一套任務機制,在此機制上面實現2個概念:
- task:resolve 任務成功
- task:reject 任務失敗回撥
我們來看下以下的內容。
通用想法
說到任務機制,我們自然會想到如下的模式:
const task = new Tasker();
task.add(async () => {
await mysql.add({
a: 1,
b: 2
})
});
task.add(async () => {
fs.writeFileSync(`/a`, `aaaaaa`, `utf8`);
});
// ....
await task.run();
複製程式碼
對,其實想法都是非常正確,再結合我們提出的概念,就變成了如下的寫法:
task.add(async function resolve() {
fs.writeFileSync(`/a`, `aaaaaa`, `utf8`);
}, async function reject() {
fs.unlinkSync(`/a`);
})
複製程式碼
確實我們是實現了簡單的任務機制。但是我們是否覺得這樣的寫法非常麻煩,那麼我們將引出我們今天的重點模組 ys-dbo
使用ys-dbo解決回滾問題
我們先來看一段程式碼:
const DBO = require(`ys-dbo`);
const dbo = new DBO();
// 這裡我們假設已經安裝了mysql模組
dbo.until(async thread => {
// 我們把之前的程式碼實現一下
const file = `/tmp/test.txt`;
await mysql.begin();
await mysql.insert(`table`, {
a: 1,
b: 2
});
fs.writeFileSync(file, `aaaaaa`, `utf8`);
thread.on(`beforeRollback`, async () => fs.unlinkSync(file));
gitlab.fork(`project`);
thread.on(`beforeRollback`, async () => gitlab.deleteProject(`project`));
}).then(...).catch(...)
複製程式碼
從上面程式碼中我們完全可以看出沒有任何task.add
的痕跡,取而代之的是beforeRollback
或者afterRollback
等事件。我們通過action+event
的模式將任務機制簡化了。
所以我們可以看一個圖:
上圖明確描述了回滾的機制,我們通過一一對應註冊的模式,來管理任務佇列。
我現在發現很多同學不愛用回滾,可能嫌棄比較麻煩的寫法,這樣寫出來的程式碼相容性不會太好。但是我們要知道回滾其實是資料處於一致性狀態的重要手段。我們要重視回滾,不在祈禱上天不要出錯。
在我們公司,我也問過很多java開發的同學,很少有人用到回滾,我就很納悶,作為一位開發工程師,不考慮嚴謹模式,這是不合格的,回滾也可以看出一個工程師的程式碼素養。
ys-dbo是什麼?
大家不用刻意在意這個模組,畢竟是個人開發實踐出來的模組,可能完善度不是很高,但是我會一直維護下去,因為畢竟自己的工作中也常用到。
npm i ys-dbo
複製程式碼
喜歡的同學點個贊吧,感謝!