【问题标题】:Injecting an ActorSystem, with actors created by Guice, in Play 2.4 for Scala在 Play 2.4 for Scala 中注入由 Guice 创建的 ActorSystem
【发布时间】:2016-01-20 05:29:44
【问题描述】:

我想做的是发送一堆电子邮件,其中的内容会针对每个用户(他们的姓名等)稍作更改。

问题是,在等待前一个阻塞后,遍历用户列表并发送每个用户列表非常慢。

所以我想我会使用 Akka 并行执行。

我用

  • 播放 2.4.3
  • play-mailer 3.0.1

这是我的演员:

import javax.inject.Inject
import akka.actor._
import play.api.libs.mailer.{MailerClient, Email}

object EmailActor {
  def props = Props[EmailActor]
  case class SendEmail(email: Email)
}

class EmailActor @Inject()(mailerClient: MailerClient) extends Actor {
  import EmailActor._

  def receive = {
    case SendEmail(email: Email) =>
      // send mail
      mailerClient.send(email)
      sender() ! "Sent"
  }
}

我设法将我的演员直接注入我的控制器,但它仍然很慢,我猜它对每条消息使用相同的演员。我想要一群演员来处理我的电子邮件!

这是我的模块

class MyModule extends AbstractModule with AkkaGuiceSupport {
  override def configure = {
    bindActor[EmailActor]("email-actor")
  }
}

这是我的控制器

@Singleton
class Emails @Inject()(system: ActorSystem) extends Controller with InjectedActorSupport {
  ...

  def sendEmailToUsers(event : Event, request:RequestHeader) : Future[Seq[String]] = {
    implicit val timeout : akka.util.Timeout = 5.seconds

    val results = event.people
      .map(user => {
        val actor = system.actorOf(EmailActor.props, "email-actor")
        (actor ? SendEmail(createEmail(event, user, request))).mapTo[String]
      })

    Future.sequence(results)
  }

我得到了异常

IllegalArgumentException: no matching constructor found on class actors.EmailActor for arguments []

我对 Akka 中的 ActorSystem 不使用 Plays 依赖注入并不感到惊讶。那我该怎么办?

问题

我如何(使用 Play 中的最佳实践)并行发送电子邮件?

【问题讨论】:

    标签: scala playframework akka playframework-2.4


    【解决方案1】:

    更换控制器

    class Emails @Inject()(@Named("email-actor") emailActor:ActorRef)(implicit ec: ExecutionContext) extends Controller{
    
       def sendEmailToUsers(event : Event, request:RequestHeader) : Future[Seq[String]] = {
          implicit val timeout : akka.util.Timeout = 5.seconds
    
          val results = event.people.map(user => {
             (emailActor ? SendEmail(createEmail(event, user, request))).mapTo[String]
          })
          Future.sequence(results)
       }
    }
    

    【讨论】:

    • 感谢您提出答案。我很感激。 :-) 但是你确定这些消息不会都发给同一个演员吗?
    【解决方案2】:

    请先检查 SMTP 服务器是否没有限制您。 ;-)

    看看Akka routing。将您的参与者重构为网关,并通过路由器将电子邮件发送委托给工作参与者。您可以使用RoundRobinRoutingLogicSmallestMailboxRoutingLogic。但不要创建过多的工作 Actor,否则 SMTP 服务器可能会限制/阻止您。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-26
      • 2019-08-16
      • 1970-01-01
      • 2019-06-06
      • 1970-01-01
      • 2015-09-30
      • 2016-08-16
      • 1970-01-01
      相关资源
      最近更新 更多