• 作成:

YesodのgetAuthEntityは内部でrunDBを使っているのでデッドロックに注意しましょう

getAuthEntity

Yesodの getAuthEntity はデフォルトでrunDBを使っています.

これがどういうことなのかと言うと, これに依存しているmaybeAuthなどを使うとYesodDBなどを見ることなくデータベースコネクションを取ってきてしまうため, runDBの内部で使ったりするとデッドロックを引き起こす危険性があります.

ユーザ情報を取ってくるので当然と言えば当然なのですが, Cookieに入っているものと混同しやすくもあります.

権限確認などを行う場合注意しましょう.

検出方法

プロファイルビルドを有効にしてrunDBactionwhoCreated をかけて出力を見ると何処からrunDBが実行されているのか確認できます.

安全確認方法

YESOD_PGPOOLSIZE1にして各ページでテストを行えばデータベースコネクションを同時に1つしか使っていないことを確認できます.

理想

runDBしたアクションをYesodDB内部に持てないようにして欲しいですね.

多分Handlerが万能すぎるのが悪いのかと思います.

runDBしたらDBRunnedみたいな型にコンテキストを包んでHandlerYesodDBに戻すのはunsafeとか命名して慎重な動作を必要とするのが良いと思います.

HandlerYesodDBに変換しにくくするのはしんどすぎるのでやめた方が良さそうですね.

そうすると現在のHaskellの型システムでもデッドロックを分かり易くできます. 現実のフレームワークにこの考えを落とし込んでプログラムしやすくなるかは実証していませんが.