У меня в моей системе два актера. Разговорчик. Разговор состоит из двух говорящих (к настоящему времени). Когда Talker хочет присоединиться к разговору, я должен проверить, существует ли разговор (другой говорящий создал его), а если нет, создайте его. У меня есть этот код в методе моего Talker актера:Получить или создать ребенка-актера по 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)
}
}
}
спасибо Арне! я узнал больше, чтобы прочитать ваш ответ, чем в дневном поиске по теме! – SergiGP
Еще один вопрос Arne. К настоящему времени я не делаю кластеризации, поэтому поиск легко, все в одной машине. Будет ли это влиять на процесс поиска, который делает маршрутизатор, когда я это сделаю? Или с прозрачностью местоположения все будет нормально работать магически? – SergiGP
Короткий ответ - да, но, вероятно, не так, как вам хотелось бы. Во-первых, по умолчанию дети роутера будут находиться на том же узле, что и сам маршрутизатор (это может быть изменено), для другого вам понадобится способ найти узел с маршрутизатором (теперь он находится в '{address} :/user/conversation'. В кластере вам, вероятно, будет лучше всего использовать реализацию вашего маршрутизатора поверх Cluster Sharding (http://doc.akka.io/docs/akka/snapshot/scala/cluster-sharding .html) –