2017-01-11 132 views
0

我目前正在与一个后台作业的应用程序,它应该定期发送我想要使用阿卡的邮件。我必须补充一点,我是Scala/Play/Akka的新手。斯卡拉和阿卡:背景工作

目前,我有以下设置:

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

这应该启动下面的一段代码,没有工作的每一秒

// 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 
} 

这可能是每一个第二多邮件应该发送。我想知道:如果我每隔一秒发送一封邮件给mailActor,它是否真的只有一个演员需要完成所有的工作,还是会有多个演员同时完成这项工作?

如果是一个演员,我怎么能有多个演员,我可以为其分配工作以及我可以/应该拥有多少演员?

回答

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个actor。累积演员中的所有消息,然后定期向自己发送一个记号。