我目前正在使用后台作业的Play应用程序,该应用程序应定期发送邮件,我想使用Akka。我必须补充一点,我是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
}
可能应该发送每个第二个多个新邮件。我想知道:如果我每隔10秒向mailActor发送一条消息,那真的只有一个演员必须完成所有的工作,还是会有多个演员同时进行这项工作?
如果是一个演员,我怎么能有多个演员为我分配作品以及我可以/应该有多少演员?
答案 0 :(得分: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("foo@bar.com", "Email will arrive in 10s"))
sendEmailEvery10s(Email("foo@bar.com", "Email will arrive in same batch"))
Thread.sleep(11000)
sendEmailEvery10s(Email("foo@bar.com", "Email will arrive after another 10s"))
Thread.sleep(11000)
killSwitch.shutdown()
}
我可能只是复杂了你的生活,但Akka流让你做这些事情而不用担心哪个演员做了什么,有背压,而且通常是更强大的代码。
如果Akka流不存在,我会使用1个演员。累积演员中的所有消息,然后定期向自己发送一个勾号。
答案 1 :(得分:0)
在示例中使用调度程序,但我看不到mailActor
如何帮助您。
actorSystem.scheduler.schedule(0 seconds, 1 seconds) {
// just call the code the the checks for email
}
不要假设会有一个帖子。即be extra careful to not close over unstable references