Лучшая практика для очистки ресурсов, приобретенных актером Акка - PullRequest
0 голосов
/ 21 ноября 2019

Мой актер Akka получает некоторые ресурсы, которые должны быть освобождены после выполнения заданий, как показано в фрагменте кода ниже.
Проблема заключается в том, как обеспечить освобождение ресурсов в случае исключений.
Первая идея пришла мне в голову - назначить полученные ресурсы var и освободить их в виде def postStop() в качестве гарантии.

Поскольку это такое распространенное требование, мне интересно, есть лилюбая лучшая практика к этому?

  override def receive: Receive = {
    case FILEIO(path) => {
      val ios = fs.create(new Path(path))
      // ios.read/write ..
      // exception could occur
      ios.close()
    }
  }

Ответы [ 2 ]

1 голос
/ 23 ноября 2019

Если вы используете Scala 2.13, вы можете попробовать scala.util.Using . Он автоматически закроет ресурс, даже если произойдет исключение.

val resultTry = Using(fs.create(new Path(path))) { ios =>
    // ios.read/write ..
    // exception could occur
}
resultTry match {
   case Success(ioOperationsResult) => ...
   case Failure(ioException) => ...
}

Кроме того, вы должны отделить блокирующие операции ввода-вывода от диспетчера akka.

0 голосов
/ 21 ноября 2019

Я думаю, вам следует пересмотреть вопрос об использовании актеров для тяжелого доступа к IO. Учитывая, что вы используете диспетчер по умолчанию, вы можете заблокировать его с помощью операций ввода-вывода, и это замедлит всю систему субъекта.

Если вы все еще хотите продолжить, рекомендуем выполнить следующие действия:

  • Создать нового диспетчера и назначить его своему актеру. См. docs для справки
  • Используйте блок try / finally для закрытия ресурсов (да, обычный старый try / catch / finally)
  override def receive: Receive = {
    case FILEIO(path) => {
      val ios = fs.create(new Path(path))
      try {
        // ios.read/write ..
        // exception could occur
      } finally {
        ios.close()
      }
    }
  }

В качестве альтернативы, извлечениеваша работа ввода-вывода в асинхронном контексте, например Future, которая должна выполняться в выделенном контексте выполнения и использовать шаблон pipeTo для обработки результатов с помощью Actor.

...