【问题标题】:message goes to dead letter instead of sender (akka router) [scala]消息转到死信而不是发件人(akka路由器)[scala]
【发布时间】:2014-09-26 19:18:49
【问题描述】:

实际上,我无法让我的演员(路由器)系统正常工作。 我的设置:

我正在尝试在播放控制器中使用 akka 路由器。对于依赖注入,我使用 scaldi。

scaldi 模块:

class UserDAOModule extends Module {
  binding to new ExampleRouter
  binding toProvider new UserDAOWorker
}

akka 路由器:

class UserDAORouter(implicit inj:Injector) extends Actor with AkkaInjectable {

  val userDAOProps = injectActorProps[UserDAOWorker]

  var router = {
    val routees = Vector.fill(5) {
      val r = context.actorOf(userDAOProps)
      context watch r
      ActorRefRoutee(r)
    }
    Router(RoundRobinRoutingLogic(), routees)
  }

  override def receive: Receive = {
    case mm: MongoDBMessage =>
      router.route(mm, sender)
    case Terminated(a) =>
      router = router.removeRoutee(a)
      val r = context.actorOf(userDAOProps)
      context watch r
      router = router.addRoutee(r)
  }

}

工人:

class UserDAOWorker(implicit inj:Injector) extends Actor with Injectable {

  val db = inject[DefaultDB]
  val collection:JSONCollection = db("users")
  val currentSender = sender

  override def receive: Receive = {
    case InsertUser(user) => insertUser(user)
  }

  def insertUser(user:User) = {
    collection.save(user).onComplete {
      case Failure(e) => currentSender ! new UserDAOReturnMessage(Some(e), None)
      case Success(lastError) => currentSender ! new UserDAOReturnMessage(None, lastError)
    }
  }
}

当我向路由器发送消息(insertUser消息)时,它被正确路由并且worker接收到消息,但是当worker将消息发送回发送者时它无法传递,所以它被发送到死信办公室。我不知道如何解决这个问题。有人可以帮助我吗?

提前致谢

【问题讨论】:

    标签: akka router actor dead-letter scaldi


    【解决方案1】:

    我猜问题是 currentSender 在创建 actor 的构造函数中被初始化为 null(即 ActorRef.noSender)。 'sender' 仅在接收()中接收消息的上下文中有效。向 ActorRef.noSender 发送消息相当于向死信队列发送消息。

    这样的事情应该可以工作:

    class UserDAOWorker(implicit inj:Injector) extends Actor with Injectable {
    
      val db = inject[DefaultDB]
      val collection:JSONCollection = db("users")
    
      override def receive: Receive = {
        case InsertUser(user) => {
          insertUser(sender, user)
        }
      }
    
      def insertUser(currentSender : ActorRef, user:User) = {
        collection.save(user).onComplete {
          case Failure(e) => currentSender ! new UserDAOReturnMessage(Some(e), None)
          case Success(lastError) => currentSender ! new UserDAOReturnMessage(None, lastError)
        }
      }
    }
    

    【讨论】:

    • 感谢您的回复。你是绝对正确的......愚蠢的错误。但即使我改变了这一点,当它调用 sender() 方法时,路由器首先已经获得了一个 ActorRef 到“死信”演员。它不应该为代表我的控制器(实际上发送实际消息)的临时 Actor 获取一个 actorRef 吗?还是我错了?也许这与我的 scaldi 配置有关..!?
    • 我刚刚发现我的绑定不正确。当我将“绑定到新的 UserDaoRouter”更改为“绑定到提供者新的 UserDaoRouter”时,它可以工作,但每次注入路由器时,都会提供一个新实例scaldi,这不是我想要的。这引出了另一个问题:stackoverflow.com/questions/26085403/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 2019-04-11
    • 2015-12-09
    • 2014-11-16
    • 2017-05-19
    • 1970-01-01
    • 2023-03-04
    相关资源
    最近更新 更多