async-lockを使った排他制御
async-lockを使ってサーバサイドで排他制御させる方法です。排他制御を使えば同時アクセスよるデータの不整合を防げます。本記事で扱うモジュールのバージョンは次のとおりです。
- Node.js - 14.16.0
- express - 4.17.1
- async-lock - 1.3.0
インストール
次のコマンドを実行します。
npm install async-lock
以降は使い方になります。
execute function を使う場合
コールバック関数を抜けてからロックが解放されます。execute function
でのエラーをコールバック関数で判定する必要があります。
実行結果
node async-lock-sample-execute.js
を実行し、ブラウザから/start-lock
> /start-lock2
の順に実行した場合の実行結果(ログ)です。
1620694694502 execute
1620694699510 sleep end
1620694699511 start-lock execute end.
1620694699511 response send start.
1620694699513 response send end.
1620694699514 execute
1620694704513 sleep end
1620694704514 start-lock2 execute end.
1620694704514 response send start.
1620694704515 response send end.
エラーを発生させる
execute function
でエラーを発生させたい場合は次のようにdone()
を実行します。
done(new Error('test exception.'));
エラー発生時の実行結果
execute function
でエラーを発生させた場合の実行結果です。
1620694953006 execute
1620694958010 sleep end
1620694958012 start-lock execute end.
test exception.
1620694958023 execute
1620694963027 sleep end
1620694963029 start-lock2 execute end.
test exception.
Promise を使う場合
then()
またはcatch()
がコールされるタイミングでロックは解除されます。
実行結果
node async-lock-sample-promise.js
を実行し、ブラウザから/start-lock
> /start-lock2
の順に実行した場合の実行結果(ログ)です。
1620696446739 execute
1620696451755 sleep end
1620696451757 execute
1620696451758 start-lock execute end.
1620696451758 response send start.
1620696451765 response send end.
1620696456764 sleep end
1620696456765 start-lock2 execute end.
1620696456765 response send start.
1620696456766 response send end.
コールバック関数のみの場合
ロック解除のタイミングはPromise
を使う場合と変わりません。
実行結果
node async-lock-sample-only-callback.js
を実行し、ブラウザから/start-lock
> /start-lock2
の順に実行した場合の実行結果(ログ)です。
1620698092689 execute
1620698097698 sleep end
1620698097700 execute
1620698097701 start-lock execute end.
1620698097702 response send start.
1620698097721 response send end.
1620698102703 sleep end
1620698102704 start-lock2 execute end.
1620698102704 response send start.
1620698102705 response send end.
ロック処理内でのエラーについて
execute function
を使う場合、Promise
を使う場合、コールバック関数のみの場合問わず、ロック処理内でエラーを発生させたい場合は次のようにdone()
を実行します。
done(new Error('test exception.'));
次のようにthrow
を使うとすると実行エラーになるので注意してください。
throw new Error('test exception.');