-
Notifications
You must be signed in to change notification settings - Fork 97
/
Copy pathExercise2.scala
68 lines (54 loc) · 2.02 KB
/
Exercise2.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.evolutiongaming.bootcamp.akka.actors
import akka.actor._
import akka.util.Timeout
import scala.concurrent._
import scala.concurrent.duration._
import scala.util.control.NoStackTrace
object Exercise2 extends App {
object AskPattern {
implicit class RichActorRef(val inner: ActorRef) extends AnyVal {
def ask(msg: Any)(implicit refFactory: ActorRefFactory, timeout: Timeout): Future[Any] =
AskPattern.ask(inner, msg)
def ?(msg: Any)(implicit refFactory: ActorRefFactory, timeout: Timeout): Future[Any] = ask(msg)
}
def ask(ref: ActorRef, msg: Any)(implicit refFactory: ActorRefFactory, timeout: Timeout): Future[Any] = {
val promise = Promise[Any]()
refFactory.actorOf(Props(new AskActor(ref, msg, timeout, promise)))
promise.future
}
final case class TimeoutException(msg: Any, timeout: Timeout)
extends RuntimeException(s"Ask timeout after $timeout on message $msg")
with NoStackTrace
/*
Actor should implement ask pattern:
- send msg to targetRef
- wait for response timeout max
- if a response (of type Any) received - complete the promise with it
- if timeout expires - fail the promise with TimeoutException
- stop (context.stop(self)) after either outcome
Use context.setReceiveTimeout!
*/
private class AskActor(
targetRef: ActorRef,
msg: Any,
timeout: Timeout,
promise: Promise[Any],
) extends Actor {
override def receive: Receive = ???
}
}
final class WorkerActor extends Actor {
override def receive: Receive = {
case "ping" =>
sender() ! "pong"
case "timeout" => // do nothing
}
}
import AskPattern._
implicit val system: ActorSystem = ActorSystem("Exercise2")
implicit val ec: ExecutionContext = system.dispatcher
implicit val timeout: Timeout = Timeout(2.seconds)
val workerRef = system.actorOf(Props(new WorkerActor), "worker")
(workerRef ? "ping").foreach(println)
(workerRef ? "timeout").failed.foreach(println)
}