Акторы Scala и общее состояние

Я пытаюсь реализовать субъект-диспетчер, который либо обрабатывает запрос, либо делегирует обработку другому субъекту в случае сбоя (на самом деле это экспоненциальный алгоритм отсрочки). Субъект диспетчера имеет логическую переменную, которая используется для решения, как направить обработку.

Правильно ли поддерживать в актере какое-то состояние? Какие проблемы могли случиться? Что мне следует использовать - транзактор (акка) или STM, чтобы избежать проблем? (Я использую актеров акка)

class DispatcherActor extends Actor {

   var backoff = false

   def receive = {
    case SendMessage(registrationId, message) => {
      if (backoff) {
        //put on the queue
        backoffManagerActor ! AddMessageToQueue(message)
      } else {
        httpClient.sendNotificationToClient(message, this)
      }
    }
    case BackoffCompleted => //set backoff to false
      backoff = false
    }

   def otherMethod = {
      backoff=true
   } 
}

person Matroska    schedule 12.02.2011    source источник
comment
Вы не должны никогда передавать экземпляр своего актера другому коду, это нарушает модель актера. Передайте ссылку на себя (ActorRef) и отправьте сообщение обратно.   -  person Viktor Klang    schedule 13.02.2011


Ответы (1)


Актеры должны поддерживать состояние, но легче всего рассуждать о них, если они изменяют это состояние только в ответ на сообщения или свои внутренние действия; если другие объекты хотят, чтобы они изменили состояние, они должны отправить сообщение.

В вашем случае я бы изменил

def otherMethod { backoff = true }

чтобы, в пределах получить,

case BeginBackoff => backoff = true

и пусть тот, кто собирался вызвать otherMethod, вместо этого отправил BeginBackoff. (Если вам нужно предпочтительно обрабатывать сообщения отсрочки передачи, вы должны использовать двухуровневый прием, который продемонстрировали другие, например, в ответ на ваш предыдущий вопрос об актерах.)

person Rex Kerr    schedule 12.02.2011
comment
Фактически otherMethod - это метод, вызываемый, когда запрос, выполняемый httpclient, завершается (nio). Это метод слушателя. Я использую асинхронный http-клиент. Так следует ли мне заменить метод слушателя передачей сообщений? Обрабатывают ли субъекты сообщения последовательно или одновременно? Спасибо - person Matroska; 13.02.2011
comment
Акторы обрабатывают сообщения последовательно, но если вы используете вложенные приемы / реакции, вы можете сначала выбрать определенные сообщения из списка. Так как это происходит последовательно, вам не нужно беспокоиться о том, что BackoffCompleted будет запущен после переменной, даже если это должно было произойти раньше. Таким образом, вы можете заставить слушателя отправлять сообщение вместо того, чтобы устанавливать логическую переменную. Однако, если вы знаете, что в безопасности от такого рода путаницы, вы можете просто переключиться на использование java.util.concurrent.atomic.AtomicBoolean вместо примитивного логического, чтобы хотя бы сохранить обновления логического значения прямо. - person Rex Kerr; 13.02.2011
comment
@Matroska - я должен добавить, что если это должно быть сверхвысокой производительностью, и вы собираетесь часто переключать флаг, вам, вероятно, не нужны накладные расходы на передачу сообщений. Актеры Scala работают прилично, но они определенно ошибаются в плане правильности и простоты рассуждений, а не производительности. - person Rex Kerr; 13.02.2011