以下のような2つのクラスタを構成するサーバの一覧があるとします。
val cluster1 = Seq("server1", "server2")
val cluster2 = Seq("server3", "server4")これらのサーバに対してFutureを使って以下のような処理を非同期で行うプログラムを書いてみよう。
- すべてのサーバに対して
http://<サーバ名>/restoreというリクエストを非同期に送信 - クラスタ単位で処理が終わったら当該クラスタのサーバに
http://<サーバ名>/activateリクエストを送信
リクエストの送信にはDispatchを使うと以下のように記述できます。
import dispatch._, Defaults._
def post(endpoint: String): Future[Either[Throwable, String]] = {
val request = url(endpoint).POST
Http(request OK as.String).either
}すぐに思いつくのは以下のような感じ。
Seq(cluster1, cluster2).foreach { cluster =>
// restoreリクエストを送信
cluster.map { server =>
post(s"http://${server}/restore")
}.map(Await.result(_, Duration.Inf)) // 待ち合わせ
// activateリクエストを送信
cluster.foreach { server =>
post(s"http://${server}/activate")
}
}途中でAwait.resultするのはダサいよねーということでこんな感じに。Future.sequence()を使うとFutureのシーケンスから1つのFutureを作ることができる。
Seq(cluster1, cluster2).foreach { cluster =>
Future.sequence(
// restoreリクエストを送信
cluster.map { server =>
post(s"http://${server}/restore")
}
).map { _ =>
// activateリクエストを送信
cluster.map { server =>
post(s"http://${server}/activate")
}
}
}