5

In a project of mine I have an akka actor for sending post requests to my google fcm server. The actor takes a list of ids and should make as many requests as there are in the list. I print out the response from the server in runForeach(println(_)) but I only get one printout for a whole list of ids. Why does this happen?

class FCMActor(val key: String) extends Actor{
  import fcm.FCMActor._
  import akka.pattern.pipe
  import context.dispatcher

  private implicit def system: ActorSystem = ActorSystem()
  final implicit val materializer: ActorMaterializer = ActorMaterializer(ActorMaterializerSettings(context.system))

  def buildBody(id: Option[String]): String = {
    Json.obj(
      "to" -> id,
      "priority" -> "high",
      "data" -> Json.obj("message" -> "Firebase Clud Message"),
      "time_to_live" -> 60
    ).toString()
  }

  def buildHttpRequest(body: String): HttpRequest = {
    HttpRequest(method = HttpMethods.POST,
      uri = s"/fcm/send",
      entity = HttpEntity(MediaTypes.`application/json`, body),
      headers = List(RawHeader("Authorization", s"key=$key")))
  }

  val connectionFlow: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] = {
    Http().outgoingConnection("fcm.googleapis.com")
  }

  def send(ids: List[Option[String]]) = {

    val httpRequests: List[HttpRequest] = ids.map(buildBody).map(buildHttpRequest)
    println(httpRequests)

    Source(httpRequests).via(connectionFlow).runForeach(println(_)) // << here I only get one println
  }

  override def receive: Receive = {
    case SendToIds(ids: List[Option[String]]) =>
      send(ids)

  }
}
Lukasz
  • 2,257
  • 3
  • 26
  • 44
  • I'm assuming you only get one response out of the flow? Maybe adding the actual logs will help clarifying this. – Stefano Bonetti Dec 30 '16 at 14:44
  • @StefanoBonetti That's what I meant to say. I only get one response out ot the flow `HttpResponse(200 OK,List(Date: Fri, 30 Dec 2016 15:10:43 GMT, Expires: Fri, 30 Dec 2016 15:10:43 GMT, Cache-Control: private, max-age=0, X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN, X-XSS-Protection: 1; mode=block, Server: GSE, Accept-Ranges: none, Vary: Accept-Encoding),HttpEntity.Chunked(application/json),HttpProtocol(HTTP/1.1))` I hope that's what you meant with logs. – Lukasz Dec 30 '16 at 15:11

1 Answers1

5

You are not consuming the response entity that the server sends you. To understand why this is important, check out the related docs page.

A quick code change to try and fix this is:

... .runForeach{ response =>
  response.discardEntityBytes()
  println(response)
}

Or, if you're actually interested in the entity, something along the lines of

... .runForeach{ _.entity.dataBytes
  .runFold(ByteString.empty) { case (acc, b) => acc ++ b }
  .map(println(_))
}
Stefano Bonetti
  • 8,973
  • 1
  • 25
  • 44