Подтвердить что ты не робот

Использование акков Akka в веб-приложении CRUD

Я работаю над веб-приложением, написанным в Scala, используя Play! и Akka. Код организован в основном так: Play контроллеры отправляют сообщения актерам Akka. Актеры, в свою очередь, разговаривают с уровнем персистентности, который абстрагирует доступ к базе данных. Типичный пример использования этих компонентов в приложении:

class OrderController(orderActor: ActorRef) extends Controller {
  def showOrders(customerId: Long) = {
    implicit request => Async {
      val futureOrders = orderActor ? FindOrdersByCustomerId(id)

      // Handle the result, showing the orders list to the user or showing an error message.
    }
  }
}

object OrderActor extends Actor {
  def receive = {
    case FindOrdersByCustomerId(id) => 
      sender ! OrderRepository.findByCustomerId(id)
    case InsertOrder(order) =>
      sender ! OrderRepository.insert(order)
      //Trigger some notification, like sending an email. Maybe calling another actor.
  }
}

object OrderRepository {
  def findByCustomerId(id: Long): Try[List[Order]] = ???
  def insert(order: Order): Try[Long] = ???
}

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

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

Итак, мой вопрос: хорошо ли использовать актеров таким образом? Каковы альтернативы написанию приложений CRUD в Scala, используя преимущества Futures и другие возможности concurrency Akka?

4b9b3361

Ответ 1

Хотя основанный на актерах concurrency не подходит для транзакционных операций из коробки, но это не мешает вам использовать актеров таким образом, если вы хорошо играете с уровнем сохранения. Если вы можете гарантировать, что вставить (запись) является атомарным, вы можете смело иметь пул актеров, делающих это для вас. Обычно базы данных имеют потокобезопасное чтение, поэтому find также работает должным образом. Кроме того, если вставить не является потокобезопасным, у вас может быть только один WriteActor, выделенный для операций записи, и последовательная обработка сообщений обеспечит вам атомарность.

Ответ 2

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

В вашем примере определяется блокирующий api репозитория, который может быть единственным, что вы можете сделать, в зависимости от вашего драйвера базы данных. Если возможно, вы должны пойти для async api, также, вернув фьючерсы. В актере вы вместо этого pipe получили результат от Будущего отправителю.