2017-01-11 5 views
0

私は現在Akkaを使用したいメールを定期的に送信するバックグラウンドジョブを持つPlayアプリケーションで作業しています。私はScala/Play/Akkaには本当に新しいことを付け加えなければなりません。ScalaとAkka:バックグラウンドジョブ

現在、私は次のセットアップを持っている:

// JobModule.scala 
bind(classOf[MailJobScheduler]).asEagerSingleton() 

これは、それは新しいメール、各第2の多重かもしれません毎秒

// MailJobScheduler.scala 
val mailActor = actorSystem.actorOf(MailActor.props, "mail-actor") 

actorSystem.scheduler.schedule(0 seconds, 1 seconds) { 
    // check how many mails have to be sent and sent messages to the mailActor 
} 

に動作します以下のコードを起動する必要があります送信する必要があります。私は疑問に思っています。メールを毎月10回送信する場合は、実際にすべての作業を行う唯一の俳優か、複数の俳優が同時に作業しますか?

1人の俳優の場合、私は仕事を割り当てることができる複数の俳優をどのように持つことができますか?

答えて

0

代わりにAkkaストリームを使用するのはどうですか?

import akka.Done 
import akka.stream.{KillSwitch, KillSwitches, OverflowStrategy} 
import akka.stream.scaladsl.{Keep, Sink, Source} 
import scala.concurrent.duration._ 
import scala.concurrent.Future 

object BatchEmailSender { 
    sealed trait Msg 
    case object Tick extends Msg 
    case class Email(toAddress: String, body: String) extends Msg 

    def apply(sendEmail: Email => Future[Done], sendInterval: FiniteDuration = 10.seconds)(implicit mat: ActorMaterializer) 
    : (Email => Unit, KillSwitch) = { 
    val emailQueue = scala.collection.mutable.Queue[Email]() 

    val (emailCmdQueue, killSwitch) = Source.queue[Msg](0, OverflowStrategy.backpressure) 
     .merge(Source.tick(0.seconds, sendInterval, Tick)) 
     .viaMat(KillSwitches.single)(Keep.both) 
     .toMat(Sink.foreach { 
     case newEmail: Email => 
      emailQueue.enqueue(newEmail) 
     case Tick => 
      emailQueue.dequeueAll(_ => true).foreach { email => 
      sendEmail(email).onFailure { case e => 
       println(s"Error sending email to ${email.toAddress}: $e") 
      } 
      } 
     })(Keep.left) 
     .run() 

    (emailCmdQueue.offer(_), killSwitch) 
    } 
} 

あなたはのsendEmail機能を必要とし、それがこのように動作します:私はちょうどあなたの人生を複雑にしているかもしれないが、アッカストリーム

import scala.concurrent.ExecutionContext.Implicits.global // TODO: remove me 

object TestApp extends App { 
    import BatchEmailSender._ 
    implicit val system = ActorSystem() 
    implicit val materializer = ActorMaterializer() 

    def sendEmail(email: Email): Future[Done] ={ 
    println(s"Sending email $email") // TODO: insert real email sender code here 
    Future.successful(Done) 
    } 

    val (sendEmailEvery10s, killSwitch) = BatchEmailSender(sendEmail) 
    sendEmailEvery10s(Email("[email protected]", "Email will arrive in 10s")) 
    sendEmailEvery10s(Email("[email protected]", "Email will arrive in same batch")) 
    Thread.sleep(11000) 
    sendEmailEvery10s(Email("[email protected]", "Email will arrive after another 10s")) 
    Thread.sleep(11000) 
    killSwitch.shutdown() 
} 

はあなたがいた俳優を気にすることなく、これらのことを行うことができます背圧があり、通常ははるかに堅牢なコードです。

Akkaストリームが存在しない場合、私は1人のアクターを使用していました。アクタ内のすべてのメッセージを累積して、定期的に自分自身に刻みを送ります。

0

この例ではスケジューラを使用していますが、mailActorがどのように役立つかはわかりません。

actorSystem.scheduler.schedule(0 seconds, 1 seconds) { 
    // just call the code the the checks for email 
} 

スレッドが1つあると想定しないでください。すなわちbe extra careful to not close over unstable references

関連する問題