Leo
Leo

Reputation: 121

Async operations with Spray, Akka, and actorSelection

I keep running into the same design problem using spray, which is how to find the original context of the Spray http request for a request, after doing some asynchronous (tell) operations in Akka.

I'm using Net-a-Porter actor per request model. It creates a child actor which I specify to handle each request, which is incapsulated by another actor which holds the correct request context.

Let let's call my actor ActorA, which has this receive method on it:

def receive: Receive = {
 case v : InputJson =>
   val id = createId
   val redisList = context.actorOf(Props[RedisListActor])
   // At this point, sender is the 'per-request' actor created, which has the HTTP context of the Spray request.
   redisList ! ListRequest(id, sender.path.toStringWithoutAddress, v)

This is adding input to a job queue on redis, which is consumed on another server. When this job is completed, the other server adds the result to a Redis PubSub queue which we are subscribed to. When an item comes into this queue, it alerts my ActorA (using context.actorOf).

case kr : KubernetesReply =>
  context.system.actorSelection(kr.actorPath) ! TaskResponse("Success", kr.payload, kr.id)

You can see that I am trying to find the original sender through using it's actorPath, but upon the KubernetesReply, I find that path is deadLetters (even though I have not explicitly killed the request actor). I've confirmed it's the correct path (i.e. I can send back the task response from the InputJson handler).

What's the correct pattern for this? How can I find my original actor, and why has it disappeared?

Upvotes: 0

Views: 171

Answers (1)

Peter Neyens
Peter Neyens

Reputation: 9820

You can put an ActorRef directly in the ListRequest message.

case class ListRequest(id: YourIdType, requestActor: ActorRef, json: InputJson)

def receive: Receive = {
  case v : InputJson =>
    val id = createId
    val redisList = context.actorOf(Props[RedisListActor])
    redisList ! ListRequest(id, sender, v)
  case kr : KubernetesReply =>
    kr.requestActor ! TaskResponse("Success", kr.payload, kr.id)
}

Upvotes: 0

Related Questions