2016-05-24 2 views
0

Я довольно новичок в актерской системе акка и блуждал, какие лучшие практики для выполнения общей логики у актера. Так вот пример:akka system - лучшая практика для выполнения общей логики между актерами

У меня есть следующий актер:

class MyActor @Inject()(eventBus: EventBus) extends Actor{ 
    eventBus.subscribe(context.self, Topics.TimeoffPolicy) 
    override def receive: Receive = { 
     case Foo(name:String) => { 
      //Need to execute foo related logic, and then Bar related logic 
     } 
     case Bar(name:String) => { 
      //Need to execute bar related logic 
     } 
     case a: Any => log.warning(f"unknown message actor ${a.toString}") 
    } 
} 

Так один вариант является для извлечения общей логики в метод и вызвать его при обработке Foo, как это:

class MyActor @Inject()(eventBus: EventBus) extends Actor{ 
    eventBus.subscribe(context.self, Topics.TimeoffPolicy) 
    override def receive: Receive = { 
     case Foo(name:String) => { 
      foo(name) 
      bar(name) 
     } 
     case Bar(name:String) => { 
      bar(name) 
     } 
     case a: Any => log.warning(f"unknown message actor ${a.toString}") 
    } 
} 

Другой вариант - отправить сообщение самому себе:

class MyActor @Inject()(eventBus: EventBus) extends Actor{ 
    eventBus.subscribe(context.self, Topics.TimeoffPolicy) 
    override def receive: Receive = { 
     case Foo(name:String) => { 
      foo() 
      self ! Bar(name) 
     } 
     case Bar(name:String) => { 
      bar(name) 
     } 
     case a: Any => log.warning(f"unknown message actor ${a.toString}") 
    } 
} 

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

То же самое происходит в случае общей логики между участниками, одним из вариантов является передача сообщения по шине событий другому игроку, чтобы вызвать, поэтому actor1 выполнит foo, а другой выполнит бар. Второй вариант состоит в том, чтобы извлечь одну и ту же логику в другой класс и вставить этот класс для обоих участников, поэтому нет, чтобы выполнить foo и bar, между участниками не будет никакой связи.

Как вы думаете?

ответ

1

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

Отправлено: self Отправлено: self Отправлено: Future Обратные вызовы (на самом деле, это единственный правильный способ, чтобы не нарушать порядок выполнения задач актера) и в запланированных действиях.

Вот фрагмент кода, чтобы проиллюстрировать синхронный подход:

class MyActor extends Actor with ActorLogging { 
    def receive = { 
    case Foo(foo) => 
     doSomeFooSpecificWork() 
     logFooOrBar() 
     sender() ! "foo done" 
    case Bar => 
     logFooOrBar() 
     sender() ! "bar done" 
    } 

    def logFooOrBar() = log.debug("A common message is handled") 
} 

И вот что я пишу для асинхронного одного:

import akka.pattern.{ask, pipe} 
class MyActor extends Actor { 
    val logger = context.actorOf(Props[DedicatedLogger]) 
    def receive = { 
    case Foo(foo) => 
     doSomeFooSpecificWork() 
     loggerActor ? LogFooOrBar(sender(), foo) pipeTo self 

    case Bar(bar) => 
     loggerActor ? LogFooOrBar(sender(), bar) pipeTo self 

    case LoggedFoo(reportTo, foo) => reportTo ! "foo done" 

    case LoggedBar(reportTo, bar) => reportTo ! "bar done" 
    } 
} 
+0

Почему отправка сообщений в себе должны быть отправлены из будущего? – Tomer

+1

Не нужно отправлять сообщения на «self» - вы можете хранить ссылку на исходный «отправитель» сообщения и отвечать на него напрямую. Во всяком случае, 'Actor' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'установлен'''' корректно, а правильность в отсутствии явной синхронизации ** гарантируется ** ** только тогда, когда весь ваш актер делает синхронно обрабатывающие сообщения, которые он получает Никакая логика, кроме отправки сообщений, никогда не должна появляться в обратных вызовах «Будущее», потому что они выполняются в других потоках, что приводит ко всем бедам параллелизма, таких как условия гонки, устаревшие данные, взаимоблокировки и т. Д. – Sergey

+0

Amm, так что, если я сохраню запись в базу данных с помощью драйвера async? У меня есть что-то вроде этого: def receive = {case X (name) => da.save (name)}, а save return - Future [String]? – Tomer