Skip to content

Instantly share code, notes, and snippets.

@miguelsaddress
Last active May 14, 2017 10:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miguelsaddress/0528fd6fb68e69d175b81a7c24bba358 to your computer and use it in GitHub Desktop.
Save miguelsaddress/0528fd6fb68e69d175b81a7c24bba358 to your computer and use it in GitHub Desktop.
import akka.actor._
import scala.concurrent.Await
import scala.concurrent.duration._
object RebelAkktorsGist extends App {
/****************************
* Messages *
***************************/
case class Command(cmd: String)
case class FYou(cmd: Command)
case class Sudo(cmd: Command)
case class SendCommandTo(cmd: Command, to: ActorRef)
case class YesMeLord(response: String)
/****************************
* Boss Actor *
***************************/
object BossActor {
def props() = Props[BossActor]
}
class BossActor extends Actor {
val actorName = self.path.name
var waitingForActors = 0
def receive = {
case SendCommandTo(cmd, actor) =>
println(s"[$actorName] Sending command [$cmd] to [$actor]")
waitingForActors += 1
actor ! cmd
case f @ FYou(c @ Command(cmd)) => {
println (s"[$actorName]: What, [${sender.path.name}]??? F* to me? F* To you!")
println(s"[$actorName]: Sending Sudo version... of [$c] to [${sender.path.name}]")
sender ! Sudo(c)
}
case YesMeLord(response) => {
waitingForActors -= 1
println(s"[$actorName]: Good boy [${sender.path.name}]... I got your response [$response]")
if (waitingForActors == 0) {
println("Terminating...")
context.system.terminate()
}
}
}
}
/****************************
* IT Guy Actor *
***************************/
object ITGuyActor {
def props(rebelChances: Double) = Props[ITGuyActor](new ITGuyActor(rebelChances))
}
class ITGuyActor(val rebelChances: Double) extends Actor {
assert(rebelChances > 0.0)
assert(rebelChances < 1.0)
val SUDO_ATTEMPTS_THRESHOLD = 3
// we are assuming only one actor sends sudo
// messages... that is ok for our purposes
// his holds state as you can see ;)
var sudoAttempts = 0
val actorName = self.path.name
override def preStart() = {
if (shouldGoRebel) {
println(s"[$actorName] Going wild...")
context.become(rebel)
}
}
def receive: Receive = {
case c @ Command(cmd) =>
println(s"[$actorName]: received command [$c]...!")
println(s"[$actorName]: I am so obedient I will do it NOW...")
sender ! YesMeLord(s"[$actorName] I executed your command [$cmd], Me Lord")
case s @ Sudo(c @ Command(cmd)) =>
println(s"[$actorName]: received Sudo command [$s]...!")
self ! c
}
def rebel: Receive = {
case c @ Command(cmd) =>
println(s"[$actorName]: received command [$c]... but FYou System!")
sender ! FYou(c)
case s @ Sudo(c @ Command(cmd)) =>
if (sudoAttempts < SUDO_ATTEMPTS_THRESHOLD) {
sudoAttempts += 1
sender ! FYou(c)
} else {
sender ! YesMeLord(s"I executed your command [$cmd] after $sudoAttempts attempts. My family got the message, Me Lord")
sudoAttempts = 0
context.stop(self)
}
}
private def shouldGoRebel: Boolean = {
val r = scala.util.Random
rebelChances > r.nextDouble
}
}
/********************************
* Run the Sample *
*******************************/
val system = ActorSystem("RebelAkktorsSystem")
val boss = system.actorOf(BossActor.props(), name = "TheBoss")
val obedientITGuy = system.actorOf(ITGuyActor.props(0.01), name = "ObedientItGuy")
val rebelITGuy = system.actorOf(ITGuyActor.props(0.95), name = "RebelItGuy")
println( "Here we go")
boss ! SendCommandTo(Command("Make me a Sandwich"), obedientITGuy)
boss ! SendCommandTo(Command("Make me a Sandwich"), rebelITGuy)
Await.ready(system.whenTerminated, 2 second)
}
Here we go
[RebelItGuy] Going wild...
[TheBoss] Sending command [Command(Make me a Sandwich)] to [Actor[akka://RebelAkktorsSystem/user/ObedientItGuy#329592640]]
[TheBoss] Sending command [Command(Make me a Sandwich)] to [Actor[akka://RebelAkktorsSystem/user/RebelItGuy#-1940265609]]
[ObedientItGuy]: received command [Command(Make me a Sandwich)]...!
[ObedientItGuy]: I am so obedient I will do it NOW...
[RebelItGuy]: received command [Command(Make me a Sandwich)]... but FYou System!
[TheBoss]: What, [RebelItGuy]??? F* to me? F* To you!
[TheBoss]: Sending Sudo version... of [Command(Make me a Sandwich)] to [RebelItGuy]
[TheBoss]: What, [RebelItGuy]??? F* to me? F* To you!
[TheBoss]: Sending Sudo version... of [Command(Make me a Sandwich)] to [RebelItGuy]
[TheBoss]: Good boy [ObedientItGuy]... I got your response [[ObedientItGuy] I executed your command [Make me a Sandwich], Me Lord]
[TheBoss]: What, [RebelItGuy]??? F* to me? F* To you!
[TheBoss]: Sending Sudo version... of [Command(Make me a Sandwich)] to [RebelItGuy]
[TheBoss]: What, [RebelItGuy]??? F* to me? F* To you!
[TheBoss]: Sending Sudo version... of [Command(Make me a Sandwich)] to [RebelItGuy]
[TheBoss]: Good boy [RebelItGuy]... I got your response [I executed your command [Make me a Sandwich] after 3 attempts. My family got the message, Me Lord]
Terminating...
Process finished with exit code 0
//////////////////////////////////////////////////////////////////////////////////////
// Here we can appreciate that the answer message of the obedient guy is received //
// earlier than the other messages, compared to the "Sample-Output-1.txt" //
//////////////////////////////////////////////////////////////////////////////////////
[RebelItGuy] Going wild...
Here we go
[TheBoss] Sending command [Command(Make me a Sandwich)] to [Actor[akka://RebelAkktorsSystem/user/ObedientItGuy#1480100196]]
[TheBoss] Sending command [Command(Make me a Sandwich)] to [Actor[akka://RebelAkktorsSystem/user/RebelItGuy#1273867621]]
[ObedientItGuy]: received command [Command(Make me a Sandwich)]...!
[ObedientItGuy]: I am so obedient I will do it NOW...
[RebelItGuy]: received command [Command(Make me a Sandwich)]... but FYou System!
[TheBoss]: Good boy [ObedientItGuy]... I got your response [[ObedientItGuy] I executed your command [Make me a Sandwich], Me Lord]
[TheBoss]: What, [RebelItGuy]??? F* to me? F* To you!
[TheBoss]: Sending Sudo version... of [Command(Make me a Sandwich)] to [RebelItGuy]
[TheBoss]: What, [RebelItGuy]??? F* to me? F* To you!
[TheBoss]: Sending Sudo version... of [Command(Make me a Sandwich)] to [RebelItGuy]
[TheBoss]: What, [RebelItGuy]??? F* to me? F* To you!
[TheBoss]: Sending Sudo version... of [Command(Make me a Sandwich)] to [RebelItGuy]
[TheBoss]: What, [RebelItGuy]??? F* to me? F* To you!
[TheBoss]: Sending Sudo version... of [Command(Make me a Sandwich)] to [RebelItGuy]
[TheBoss]: Good boy [RebelItGuy]... I got your response [I executed your command [Make me a Sandwich] after 3 attempts. My family got the message, Me Lord]
Terminating...
Process finished with exit code 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment