Как управлять одновременными ссылками на одного и того же персистентного актера - PullRequest
0 голосов
/ 10 мая 2019

Я пробую Akka Persistance и столкнулся с проблемой одновременного доступа к одному и тому же персистентному субъекту. Речь идет о том, чтобы на каждом идентификаторе работал не более одного экземпляра.

У меня есть простой постоянный актер, называемый CustomerActor, который обладает некоторыми простыми функциональными возможностями лабораторного назначения, для пояснения давайте назовем его свойством A, состояние которого изменяется с помощью команды и сохраняется с использованием источника событий. Приложение принимает параллельные входные данные, что означает, что если я в коде обращаюсь к CustomerActor следующим образом:

val customerActor = system.actorOf(Props(classOf[CustomerActor], "SE",id), CustomerActor.name("SE", id))

где код может выполняться одновременно (val customerActor является локально значимым значением, поэтому для двух одновременно выполняемых вызовов будет два экземпляра CustomerActor, каждый из которых является источником, полученным из постоянного хранилища. Я фактически не знал об этом, пока не обнаружил неожиданные результаты при одновременном выполнении вычислений с одним и тем же объектом.

Теперь, если я сделаю

val customerActorFuture = system.actorSelection("user/customeractor.SE.{$id}").resolveOne()

val customerActor = Await.result(customerActorFuture, timeout.duration)

Я буду использовать тот же экземпляр, и все будет в порядке, если не будет условий гонки и время поиска CustomerActor достаточно короткое. Мой вопрос: существует ли какой-то современный стандарт для этого, которого мне не хватает? Мне нужно убедиться, что я использую ровно один экземпляр постоянного субъекта, который является одной из основных функций, которые мы хотим использовать для этого. Поэтому я действительно ожидал, что system.actorOf будет иметь семантику «создайте новый экземпляр только, если его еще нет», защищая от очевидного состояния гонки, если я использую actorSelection (два потока «одновременно», обнаружив, что актера нет, и, следовательно, создавая на каждый.

Благодарен за уточняющий ответ на этот вопрос.

Редактировать:

Я допустил глупую ошибку, которая испортила поведение приложения: из двух ссылок на актеров, полученных с помощью system.actorOf, я забыл использовать аргумент имени во втором.

Конечно, это не может работать, так как тогда имя будет сгенерировано Akka, и будет два отдельных экземпляра CustomerActor с одинаковым идентификатором персистентности. Теперь я исправил код, чтобы использовать параметр имени в обоих случаях, а затем я получил ожидаемое поведение: создавайте актера, только если он еще не существует с указанным именем.

Я оставлю вопрос здесь, может ли он помочь другим в будущем ...

...