LoginSignup
6
6

More than 5 years have passed since last update.

scala playframework slick におけるコンテキストスイッチ

Last updated at Posted at 2016-11-12

注意

挙動を試してないので確証はまだないけど、とりあえずの備忘として残した記事です。

突然の死

ある日突然リクエストを受け付けるが処理が走らずエラーを返すようになってしまった。

正直なぜそうなったのか分からず、なんやかんやあってスレッドが怪しいのでは?となった。

スレッドの動き

netty のスレッド -> playframework のスレッド -> slick のスレッド

らしい。

DBIO の処理

DBIOの処理はこんな感じで書かれていた

for {
  _ <- DBIO型を返す
  _ <- DBIO型を返す
} yield ()

for は flatMap になる

slick の flatMap による DBIO合成

  def flatMap[R2, S2 <: NoStream, E2 <: Effect](f: R => DBIOAction[R2, S2, E2])(implicit executor: ExecutionContext): DBIOAction[R2, S2, E with E2] =
FlatMapAction[R2, S2, R, E with E2](this, f, executor)

flatMapによる合成は implicit executor: ExecutionContext を要求する

playframework のスレッドで動いていた処理が slick でのDBIOの処理に移る(slickのスレッドに移る)とコンテキストスイッチが発生する。(らしい)

たしかに ExecutionContext を分けているのでそうなのだろう。

flatMapされる毎にコンテキストスイッチが発生。

play thread -> slick thread
play thread <- slick thread

というような状況になり、ある時

play thread 1 -> slick thread 1

slick thread 1に移った時点で play thread は開放されているので別の処理で使われる

play <- slick thread 1

slick thread 1 の処理が終わった時点で play thread が空いていないと処理を返せないので slick thread 1を握ったまま待つ。

play thread 1 -> slick

slick thread が空いていないので slick thread が空くのを待つ。

という状況に陥ったのでは無いかという推測。

ちなみに
DBIO.seq とか andThen であれば ExecutionContext を要求しないので同じスレッドで動くのでは?というお話

しかも

最悪なことに Await.result(しかも Duration.Inf ) されていたため、処理を待ち続けてスレッドを掴み続けていました。

ていうか

問題発生時にRejectedExecutionException出さないの?
やっぱりよくわからん。
Await.result の Duration.Infで延々と待ち続けるからエラー吐かないとか?

reactive slick

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6