LiftRules.addAroundで追加したaroundがなぜか2度呼ばれる
liftにはaroundと呼ばれるリクエスト処理をハンドルする為の機構が用意されていて、こんなコードで例えばログを残すことができる。と、公式サイトには書いてある。
(参照: http://liftweb.net/index.php/HowTo_hook_into_the_lift%27s_request_processing_cycle)
S.addAround(List(new LoanWrapper { def apply[T](f: => T): T = { TimeHelpers.logTime("何かの処理")(f) } }))
が、どうも一回のリクエストで2個ログが表示されるのだ。
INFO - 何かの処理 took 15 Milliseconds INFO - 何かの処理 took 265 Milliseconds INFO - Service request (GET) / took 469 Milliseconds
調べてみるとdispatchTableの処理とLiftSession.processRequestの先頭と2回呼ばれている。
どうしてこんなことになっているかと推測するに、dispatchTableはレスポンスが帰ってきたらそこで処理を打ち切る構造になってるが故にまったく処理されなかったときにaroundが不要に呼ばれることに。その後Session処理を呼んだときにやはりaround処理を呼ばないといけないので2度呼ばれるようだ。
そこで、リクエストが処理されたときだけ何かしたい場合は、結果が返ってきたら処理されているという判定を加えればよさそうだ。なのだが、fの戻り型はTとしか規定されていない^^;ハンドラの型が規定されてないってどうよ?
で、Tに一体何が来うるかというと使ってる箇所を調べると1つはTuple2[boolean,Can[Response]]でもう1つはCan[Response]のようだ。
なので将来変わって動かなく可能性があるちょっと危険なコードになった。
S.addAround(List(new LoanWrapper { def apply[T](f: => T): T = { val (time,result) = TimeHelpers.calcTime(f) def logTime = Log.info("何かの処理 took "+time+" Milliseconds") result match { case (_,Full(_)) => logTime case Full(_) => logTime case _ => } result }}))
もっと良いやり方を知っている方は是非教えてください。