我想做的是发送一堆电子邮件,其中每个用户的内容都会发生一些变化(他们的名字等)。
问题是,在等待前一个阻止之后,通过用户列表进行迭代并发送每个用户是非常慢的。
所以我以为我会使用Akka并行完成。
我用
这是我的演员:
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中的最佳做法),并行发送电子邮件?
答案 0 :(得分:0)
更改控制器
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)
}
}
答案 1 :(得分:0)
请先检查SMTP服务器是否不会限制您。 ; - )
看看Akka routing。将您的actor重构为网关,并通过路由器将发送的电子邮件委派给工作人员。您可以使用RoundRobinRoutingLogic
或SmallestMailboxRoutingLogic
。但是不要创建太多的工作程序,否则SMTP服务器可能会限制/阻止你。