Я пробую 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 с одинаковым идентификатором персистентности.
Теперь я исправил код, чтобы использовать параметр имени в обоих случаях, а затем я получил ожидаемое поведение: создавайте актера, только если он еще не существует с указанным именем.
Я оставлю вопрос здесь, может ли он помочь другим в будущем ...