Future(new SomeObject) } class HeavyTaskService @Inject()(repository: SomeObjectRepository) (implicit ec: HeavyTaskExecutionContext) { def execHeavyTask: Future[Int] = { Future { val i = Await.result(repository.getSomeObject.map(obj => obj.someField), 100.millisecond) heavyTask(i) // 時間がかかる処理 i } } } ① ② ③ ④ SomeObjectRepositoryEx ecutionContextを使って実 行される ①
Future[List[Int]] = { DB.futureLocalTx { implicit session => val ids = sql"""select id from members""".map(rs => rs.long("id")).toList().apply() Future.sequence(ids.map { id => val newName = s"userId$id" Future(sql"""update members set name = $newName where id = $id""".update.apply()) }) } } } ※コードを簡略化するために、DBアクセス部分をScalikejdbcを使っています
Future[List[Int]] = { DB.futureLocalTx { implicit session => val ids = sql"""select id from members""".map(rs => rs.long("id")).toList().apply() Future.sequence(ids.map { id => val newName = s"userId$id" Future(sql"""update members set name = $newName where id = $id""".update.apply()) }) } } } ①. DBのトランザクションを開始し、引数の関数が返す Futureが完了したらトランザクションをコミット。 失敗したらロールバック ①
Future[List[Int]] = { DB.futureLocalTx { implicit session => val ids = sql"""select id from members""".map(rs => rs.long("id")).toList().apply() Future.sequence(ids.map { id => val newName = s"userId$id" Future(sql"""update members set name = $newName where id = $id""".update.apply()) }) } } } ①. DBのトランザクションを開始し、引数の関数が返す Futureが完了したらトランザクションをコミット。 失敗したらロールバック ① ②. DBから取得したIDのリストを使って、複数の updateを実行するFuture生成し、それを Future.sequenceを使って一つのFutureにまとめる 基のFutureの結果をまとめるだけなので、それぞれの Futureは別スレッドで実行される ②
Future[List[Int]] = { DB.futureLocalTx { implicit session => val ids = sql"""select id from members""".map(rs => rs.long("id")).toList().apply() Future.sequence(ids.map { id => val newName = s"userId$id" Future(sql"""update members set name = $newName where id = $id""".update.apply()) }) } } } ①. DBのトランザクションを開始し、引数の関数が返す Futureが完了したらトランザクションをコミット。 失敗したらロールバック ① ② updateを複数のスレッドで並列実行できるので速くなりそうに見えるが、 短時間に複数のスレッドからこのメソッドが呼び出されると、DBのロック解放待ち状態の スレッドが大量にできて、しばらくこのExecutionContextは処理を実行できなくなる ②. DBから取得したIDのリストを使って、複数の updateを実行するFuture生成し、それを Future.sequenceを使って一つのFutureにまとめる 基のFutureの結果をまとめるだけなので、それぞれの Futureは別スレッドで実行される