我的系統中有兩名演員。談話者和談話。談話由兩個談話者組成(到目前爲止)。當說話者想要加入對話時,我應該檢查對話是否存在(另一個說話者已經創建了它),如果不存在,請創建它。我有這樣的代碼在我發話演員的方法:通過ID獲取或創建小孩演員
def getOrCreateConversation(conversationId: UUID): ActorRef = {
// @TODO try to get conversation actor by conversationId
context.actorSelection("user/conversation/" + conversationId.toString)
// @TODO if it not exists... create it
context.actorOf(Conversation.props(conversationId), conversationId.toString)
}
正如你所看到的,當我創建我的converastion演員與actorOf我傳遞的第二個參數的conversationId。我這樣做是爲了方便搜索這位演員......這是做到這一點的正確方法嗎?
謝謝
編輯
感謝@Arne我終於做到了這一點:
class ConversationRouter extends Actor with ActorLogging {
def receive = {
case ConversationEnv(conversationId, msg) =>
val conversation = findConversation(conversationId) match {
case None => createNewConversation(conversationId)
case Some(x) => x
}
conversation forward msg
}
def findConversation(conversationId: UUID): Option[ActorRef] = context.child(conversationId.toString)
def createNewConversation(conversationId: UUID): ActorRef = {
context.actorOf(Conversation.props(conversationId), conversationId.toString)
}
}
而且測試:
class ConversationRouterSpec extends ChatUnitTestCase("ConversationRouterSpec") {
trait ConversationRouterSpecHelper {
val conversationId = UUID.randomUUID()
var newConversationCreated = false
def conversationRouterWithConversation(existingConversation: Option[ActorRef]) = {
val conversationRouterRef = TestActorRef(new ConversationRouter {
override def findConversation(conversationId: UUID) = existingConversation
override def createNewConversation(conversationId: UUID) = {
newConversationCreated = true
TestProbe().ref
}
})
conversationRouterRef
}
}
"ConversationRouter" should {
"create a new conversation when a talker join it" in new ConversationRouterSpecHelper {
val nonExistingConversationOption = None
val conversationRouterRef = conversationRouterWithConversation(nonExistingConversationOption)
conversationRouterRef ! ConversationEnv(conversationId, Join(conversationId))
newConversationCreated should be(right = true)
}
"not create a new conversation if it already exists" in new ConversationRouterSpecHelper {
val existingConversation = Option(TestProbe().ref)
val conversationRouterRef = conversationRouterWithConversation(existingConversation)
conversationRouterRef ! ConversationEnv(conversationId, Join(conversationId))
newConversationCreated should be(right = false)
}
}
}
謝謝Arne!我已經學會了更多的閱讀你的答案,而不是在一天中搜索這個主題! – SergiGP
另一個問題Arne。現在我沒有進行集羣化,所以查找很容易,一切都在同一臺機器上。它會影響到路由器在執行時的查找過程嗎?或者與位置透明度一切都會神奇地正常工作? – SergiGP
簡短的回答是肯定的,但可能不是你想要的。首先,默認情況下,路由器的子節點都與路由器本身在同一個節點上(這可能會改變),對於另一個需要使用路由器查找節點的方法(現在位於'{address} :/ user/conversation'。在一個集羣中,你最好的方法是在集羣分片之上使用你的路由器(http://doc.akka.io/docs/akka/snapshot/scala/cluster-sharding的.html) –