Внедрение ActorSystem с акторами, созданными Guice, в Play 2.4 для Scala

Что я хочу сделать, так это разослать кучу электронных писем, в которых содержимое немного изменяется для каждого пользователя (их имя и т. Д.).

Проблема в том, что очень медленно перебирать список пользователей и отправлять каждого из них после ожидания предыдущей блокировки.

Я подумал, что сделаю это параллельно, используя 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 []

Я не удивлен, что ActorSystem в Akka не использует инъекцию зависимостей Plays. Так что я должен делать?

Вопрос

Как я могу (используя лучшие практики в Google Play) отправлять электронные письма параллельно?


person tomaj    schedule 21.10.2015    source источник


Ответы (2)


изменить контроллер

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)
   }
}
person Isman Usoh    schedule 27.10.2015
comment
Спасибо, что предложили ответ. Я ценю это. :-) Но вы уверены, что не все сообщения отправляются одному и тому же актеру? - person tomaj; 27.10.2015

Сначала убедитесь, что SMTP-сервер вас не ограничивает. ;-)

Взгляните на маршрутизацию Akka. Выполните рефакторинг своего актора до шлюза и делегируйте отправку электронной почты рабочим акторам через маршрутизатор. Вы можете использовать RoundRobinRoutingLogic или SmallestMailboxRoutingLogic. Но не создавайте слишком много рабочих акторов, иначе SMTP-сервер может задушить / заблокировать вас.

person Sebastian    schedule 13.03.2016