我是Akka的新手,Scala。
我必须构建一个服务,该服务会发送附带给emailIds附件的电子邮件。我使用Sendgrid作为网关。
对于附件,我在S3中上传了一个大小为28KB的文件。
我有REST服务,我可以通过它传递文档ID,我可以通过该服务将文档作为InputStream获取。现在,此输入流必须发送到许多电子邮件ID。下载文件的所有内容都由一个名为“attachmentActor”的actor处理,我在下面创建。
现在假设我有两个我需要发送附件的emailIds,我面临的问题是它没有向两者发送完整文件,事实上28KB文件分为16KB和12KB,最后发送到emailIds。 / p>
所以emailId 1会收到16KB //实际应该有28KB
电子邮件2将收到12KB //它应该实际上有28KB
以下是代码:
class SendgridConsumer{
def receive(request: EmailRequest) = {
val service = Sendgrid(username , password)
val logData = request.logData
var errorMessage = new String
val attachmentRef = system.actorOf(Props[AttachmentRequestConsumer], "attachmentActor")
val future = attachmentRef ? AttachmentRequest(request.documentId.get)
var targetStream = Await.result(future, timeout.duration).asInstanceOf[InputStream]
val results = request.emailContacts.par.map( emailContact => {
val email=postData(new Email(),request , emailContact, targetStream,request.documentName.get)
val sendGridResponse=service.send(email)
}
}
// postData() creates an Email Object
// This is my Attachment Actor
class AttachmentRequestConsumer extends Actor with ActorLogging {
def receive = {
case request:AttachmentRequest => {
log.info(" inside Attachment RequestConsumer with document Id:" + request.documentId)
val req: HttpRequest = Http(url)
val response = req.asBytes
val targetStream = ByteSource.wrap(response.body).openStream()
log.info("response body :" + response.body)
sender ! targetStream
targetStream.close()
}
}
}
答案 0 :(得分:3)
你应该了解的关于actor的一件事是你不应该将可变对象(例如InputStream)作为消息发送(从技术上讲,只要你不改变它们就可以)。另一件事是发送消息是异步的。这意味着在另一个actor收到消息之前调用targetStream.close()
。这可能是您获得截断附件的原因。
您可以做的一件事是发送数据而不是InputStream
。像
def receive = {
case request:AttachmentRequest => {
log.info(" inside Attachment RequestConsumer with document Id:" + request.documentId)
val req: HttpRequest = Http(url)
val response = req.asBytes
val data = ByteSource.wrap(response.body).read.toVector
log.info("response body :" + response.body)
sender ! data
}
}
即如果您可以将附件的内容舒适地放入内存中。如果不是这种情况,您可以尝试break it into chunks or something.
在旁注中,您不应该在接收时阻止(Await.result
)。更好的方法是向AttachmentRequestConsumer发送一条消息,然后在Seq[Byte]
的接收中返回AttachmentResponse
类型的消息(或者甚至更好的某些包装器,如SendgridConsumer
)。