Как остановить Actor использующий Future ?

58 views
Skip to first unread message

Konstantin Palyanichka

unread,
Nov 27, 2016, 11:41:36 PM11/27/16
to Scala в России
есть 2 примера кода.
Первый пример успешно выполняется и завершается:

case class Scrap(url:String)
case class Stop()

class Scrapper extends Actor with ActorLogging {
var count = 0

def getDoc(url: String): org.jsoup.nodes.Document = {
val user_agent: String = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1"
val response = Jsoup.connect(url).timeout(3000).ignoreContentType(true).userAgent(user_agent).execute()
val contentType: String = response.contentType
val doc = response.parse()
doc }

override def postStop() = {
context.system.terminate
}
def receive = {
case Scrap(url) =>
println(s"scraping $url")
val content = getDoc(url)
println(content.title)
count += 1
}
}
object Main extends App{
implicit val timeout = Timeout(2 seconds)
val system = ActorSystem()

val supervisor = system.actorOf(Props(new Scrapper ))
for(i<-0 to 10 ) {
supervisor ! Scrap("http://football.ua")
}
supervisor ! PoisonPill

}

Второй пример, с использованием Future в receive, выполняется, но не завершается.

def receive = {
case Scrap(url) =>
println(s"scraping $url")
val content = Future{getDoc(url)}
content onComplete {
case Success(content)=>
println(content.title)
count += 1
case Failure(content)=>
println("Failure")

}

object Main extends App{
implicit val timeout = Timeout(2 seconds)
val system = ActorSystem()

val supervisor = system.actorOf(Props(new Scrapper ))
for(i<-0 to 10 ) {
supervisor ! Scrap("http://football.ua")
}

Await.result(system.whenTerminated, Duration.Inf)
supervisor ! PoisonPill
}

Прошу подсказки в вопросе

Nikolay Artamonov

unread,
Nov 28, 2016, 4:47:58 AM11/28/16
to scala-...@googlegroups.com
Поменять местами последние две строки второго примера не пробовали?

  Await.result(system.whenTerminated, Duration.Inf)
  supervisor ! PoisonPill




--
--
Страница рассылки: http://groups.google.com/group/scala-russian

---
Вы получили это сообщение, поскольку подписаны на группу Scala в России.

Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес scala-russian+unsubscribe@googlegroups.com.
Настройки подписки и доставки писем: https://groups.google.com/d/optout.



--
С уважением,
Артамонов Николай
mailto:narta...@gmail.com

Sergey Scherbina

unread,
Nov 28, 2016, 8:41:31 AM11/28/16
to scala-...@googlegroups.com
Вам правильно посоветовали поменять местами две последние строчки но на этом Ваши проблемы к сожалению не закончатся - 
фьючеры не будут успевать ничего сделать поскольку актор не ждет их выполнения и сразу будет получать таблетку с ядом и все будет быстро заканчиваться - 
одним словом у вас некорректная архитектура (если так можно вообще сказать). 

Я бы советовал примерно вот так:

case class Scrap(urls: Seq[String])
case class Stop()


implicit val timeout = Timeout(2 seconds)
val system = ActorSystem()

import system.dispatcher


class Scrapper extends Actor with ActorLogging {
var count = 0

  def getDoc(url: String): String = {
println(s"getDoc($url)")
Thread.sleep(1000) // here is your job ...
url

}

override def postStop() = {
context.system.terminate
}

def receive = {
    case Scrap(urls) =>
Await.ready(
Future.sequence(urls map (url =>
Future(Right[Throwable, String](getDoc(url))).recover {
case t: Throwable => Left[Throwable, String](t)
})).map(_.collect {
case Right(content) =>
count += 1
println("Content: " + content)
case Left(failure) =>
println("Failure:" + failure)
}), (urls.size * 2) seconds)
}
}

val supervisor = system.actorOf(Props(new Scrapper))
supervisor ! Scrap(Seq.fill(10)("http://football.ua"))
Await.result(gracefulStop(supervisor, 10 seconds), 11 seconds)

--
With regards,
Sergey Scherbina

Message has been deleted

Konstantin Palyanichka

unread,
Nov 28, 2016, 9:08:27 AM11/28/16
to Scala в России
Cергей, спасибо. Я так и думал, что проблема в понимании работы акторов и архитектуры 
Николай, менять строки я пробовал :)... Если так делать, то очередь PoisonPill настанет ранее нежели какого то Future c моим get request  

Sergey Scherbina

unread,
Nov 28, 2016, 9:26:31 AM11/28/16
to scala-...@googlegroups.com
Константин, как Вы уже наверное поняли, Вам нужно тут продумать правильную архитектуру. По этому поводу у меня пока возник такой вопрос - а зачем вам здесь вообще нужны какието акторы? :)
В данном конкретном случае в принципе вообще достаточно одних только фьючеров - какой либо особой пользы именно от акторов я пока не вижу (в Вашем конкретном примере если - в общем случае конечно акторы могут быть нужны).


--
With regards,
Sergey Scherbina

28 ноября 2016 г., 15:06 пользователь Konstantin Palyanichka <k.paly...@gmail.com> написал:
Сергей, спасибо. Я так и думал, что проблема в понимании работы акторов и архитектуры 
Николай, менять строки я пробовал :)... Если так делать, то очередь PoisonPill настанет ранее нежели какого то Future c моим get request  

понедельник, 28 ноября 2016 г., 7:41:36 UTC+3 пользователь Konstantin Palyanichka написал:

--
--
Страница рассылки: http://groups.google.com/group/scala-russian

---
Вы получили это сообщение, поскольку подписаны на группу "Scala в России".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес scala-russian+unsubscribe@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Konstantin Palyanichka

unread,
Nov 28, 2016, 10:25:31 AM11/28/16
to Scala в России
Сергей, это чисто учебный пример для меня.
А если в целом, то думал , дальше в обучении, написать Crawler, с иcпользованием  Akka, который будет парсить сайт а результаты писать в БД. 

Сергей, может Вы можете посоветовать какие то туториалы или интересные книги(сейчас читаю learning akk Jason Goodwin) по akka ? 
Кстати, по примеру,  если количество элементов в Seq изменить на 1000, то постоянно вылазить OutOfMemoryError.  

понедельник, 28 ноября 2016 г., 17:26:31 UTC+3 пользователь Sergey Scherbina написал:
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес scala-russia...@googlegroups.com.

Никита Ковалёв

unread,
Nov 28, 2016, 11:26:08 AM11/28/16
to scala-...@googlegroups.com
Добрый вечер.

Как ни странно звучит, в дополнении к книге, в офиц. доке (http://doc.akka.io/docs/akka/2.4/scala.html) есть ответы на многие концептуальные вопросы, в частности в первых разделах и how to.

28 ноября 2016 г., 18:25 пользователь Konstantin Palyanichka <k.paly...@gmail.com> написал:
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес scala-russian+unsubscribe@googlegroups.com.

Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.



--
С уважением
Ковалёв Никита.
nik...@maizy.ru

Sergey Scherbina

unread,
Nov 28, 2016, 12:45:15 PM11/28/16
to scala-...@googlegroups.com
Константин, попробуйте посмотреть в сторону так называемого реактивного программирования, например Akka Streams (но это только как вариант один из многих).

Но в любом случае какой либо одной панацеи не существует и правильное решение Вам все таки придется искать самостоятельно :)

28 нояб. 2016 г., в 16:25, Konstantin Palyanichka <k.paly...@gmail.com> написал(а):

Sergey Scherbina

unread,
Nov 29, 2016, 5:55:55 AM11/29/16
to scala-...@googlegroups.com
Константин, кстати - Вы вполне можете для начала поступить так - вместо того чтобы в запросе актору отправлять сразу 1000 заданий одним запросом, Вы можете отправить 100 запросов по 10 заданий, примерно так

 for(i<-0 to 10 ) {
   supervisor ! Scrap(Seq.fill(10)("http://football.ua"))
}



--
With regards,
Sergey Scherbina

28 ноября 2016 г., 18:45 пользователь Sergey Scherbina <sergey.s...@gmail.com> написал:
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес scala-russian+unsubscribe@googlegroups.com.

Sergey Scherbina

unread,
Nov 29, 2016, 5:57:02 AM11/29/16
to scala-...@googlegroups.com
точнее так :)

for(i<-0 to 100 ) {
   supervisor ! Scrap(Seq.fill(10)("http://football.ua"))
}

--
With regards,
Sergey Scherbina

29 ноября 2016 г., 11:55 пользователь Sergey Scherbina <sergey.s...@gmail.com> написал:
Reply all
Reply to author
Forward
0 new messages