Background
以前投稿したakka-pusherではeventを1つずつ投げていたので、API Call数でプランが変わるpusherでは結構致命的です。
そこで、batch requestに対応しました。
対応PR: https://github.com/dtaniwaki/akka-pusher/pull/22
How to make the batch request
Akka Actorのschedulerを使いました。
まずSchedule TaskをActor
で受け取るためのcase class
を作成します。
case class BatchTriggerTick()
そして、schedulerを使ってBatchTriggerTick
を自分自身に一定間隔で投げます。
class PusherActor(config: Config = ConfigFactory.load()) extends Actor {
// ...
system.scheduler.schedule(
1000 milliseconds,
1000 milliseconds,
self,
BatchTriggerTick()))
// ...
}
本来はbatch modeでない時にメッセージを送るためのTriggerMessage
をbatch modeでも使い回したかったのですが、pusher側で複数指定できるchannels
ではなく個別指定のchannel
を使わなければならないという制限があるため、別途BatchTriggerMessage
を使用します。
そして、BatchTriggerMessage
を受け取った時は送信せずにキューに貯め、BatchTriggerTick
を受け取った時にキューにあるメッセージをまとめてpusherに投げるようにしました。
class PusherActor(config: Config = ConfigFactory.load()) extends Actor {
// ...
protected val batchTriggerQueue = Queue[BatchTriggerMessage]()
override def receive: Receive = {
case trigger: BatchTriggerMessage =>
batchTriggerQueue.enqueue(trigger)
true
case BatchTriggerTick() =>
val triggers = batchTriggerQueue.dequeueAll { _ => true }
triggers.grouped(batchNumber) foreach { triggers =>
pusher.trigger(triggers.map(BatchTriggerMessage.unapply(_).get)).map {
case Success(_) => // Do Nothing
case Failure(e) => logger.warn(e.getMessage)
}
}
triggers.length
}
// ...
}
pusherの受け付けるevent数が最大100なので、100ずつに区切っています。
実際に動くものをheroku上に作ってみました。
これを使ってチャットアプリのバックエンドが簡単に作れるようになりました。