Skip to content

Commit

Permalink
Playing around with the many options offered by typed actors.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabi Volpe committed Aug 5, 2016
1 parent 1bb29cb commit 2a76064
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 10 deletions.
59 changes: 53 additions & 6 deletions src/main/scala/com/gvolpe/typed/Demo.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.gvolpe.typed

import akka.actor._
import de.knutwalker.akka.typed._
import com.gvolpe.typed.actor.TypedActorExample
import com.gvolpe.typed.actor.TypedActorExample.{Bar, Foo}
import com.gvolpe.typed.actor.SimpleAkkaActor.{SimpleMessage, SimpleMessageOne, SimpleMessageTwo}
import de.knutwalker.akka.typed.{ActorRef, _}
import com.gvolpe.typed.actor._
import com.gvolpe.typed.actor.SimpleTypedActor._
import com.gvolpe.typed.actor.StrictTypedActor.StrictOne
import com.gvolpe.typed.actor.UnionTypedActor._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
Expand All @@ -14,13 +17,57 @@ object Demo extends App {

case object SomeOtherMessage

val actor = TypedActorExample.props
val actor = SimpleTypedActor.props

actor ! Foo("Hey you!")
actor ! Foo("Hey you be strict!")
actor ! Bar("What's the craic?")

// You'll get a compilation error!
//actor ! SomeOtherMessage
// actor ! SomeOtherMessage

val unionActor = UnionTypedActor.props

unionActor ! SampleOne(5)
unionActor ! SampleTwo("Hey!")
unionActor ! SampleThree(false)

// You'll get a compilation error!
// unionActor ! SomeOtherMessage

val untypedActor: UntypedActorRef = unionActor.untyped

val sampleTwoOnlyActor = unionActor.only[SampleTwo]

sampleTwoOnlyActor ! SampleTwo("Hello!")

// You'll get a compilation error!
// sampleTwoOnlyActor ! SampleOne(1)

val simpleAkkaActor: UntypedActorRef = SimpleAkkaActor.props

simpleAkkaActor ! SimpleMessageOne("Hey!")
simpleAkkaActor ! "Whatever, it's untyped!"

val simpleAkkaActorTyped: ActorRef[SimpleMessage] = simpleAkkaActor.typed[SimpleMessage]

simpleAkkaActorTyped ! SimpleMessageTwo("Hey!")

// You'll get a compilation error!
// simpleAkkaActorTyped ! "Now it will fail!"

val strictTypedActor = StrictTypedActor.props

strictTypedActor ! StrictOne

// You'll get a compilation error!
// strictTypedActor ! "Whatever"

val strictUnionTypedActor = StrictUnionTypedActor.props

strictUnionTypedActor ! StrictUnionTypedActor.Foo()

// You'll get a compilation error!
// strictUnionTypedActor ! "Whatever"

system.scheduler.scheduleOnce(2.seconds)(system.terminate())

Expand Down
34 changes: 34 additions & 0 deletions src/main/scala/com/gvolpe/typed/ReplyToPatternDemo.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.gvolpe.typed

import akka.actor.ActorSystem
import com.gvolpe.typed.actor.{BrokenReplyToPatternActor, ReplyToPatternActor}
import de.knutwalker.akka.typed._

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._

object ReplyToPatternDemo extends App {

implicit val system = ActorSystem("typed-actors-demo")

case class MyMessage(payload: String)
case class MyResponse(payload: String)

import akka.actor.ActorDSL._
val box = inbox()

val brokenReplyToPatternActor: ActorRef[MyMessage] = Typed[BrokenReplyToPatternActor].create()
box.send(brokenReplyToPatternActor.untyped, MyMessage("ReplyTo Pattern!"))

val result: Any = box.receive(1.second)
// val MyResponse(result) = box.receive(1.second) // This will throw a MatchError in Runtime!!!

val replyToPatternActor: ActorRef[MyMessage] = Typed[ReplyToPatternActor].create()
box.send(replyToPatternActor.untyped, MyMessage("ReplyTo Pattern!"))

val MyResponse(response) = box.receive(1.second) // Now it works!
println(response)

system.scheduler.scheduleOnce(2.seconds)(system.terminate())

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.gvolpe.typed.actor

import com.gvolpe.typed.ReplyToPatternDemo.MyMessage
import de.knutwalker.akka.typed._

case class BrokenReplyToPatternActor() extends TypedActor.Of[MyMessage] {
override def typedReceive: TypedReceive = {
case m: MyMessage => sender() ! m.payload
}
}
10 changes: 10 additions & 0 deletions src/main/scala/com/gvolpe/typed/actor/ReplyToPatternActor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.gvolpe.typed.actor

import com.gvolpe.typed.ReplyToPatternDemo.{MyMessage, MyResponse}
import de.knutwalker.akka.typed._

case class ReplyToPatternActor() extends TypedActor.Of[MyMessage] {
override def typedReceive: TypedReceive = {
case m@MyMessage(payload) => sender() ! MyResponse(payload)
}
}
20 changes: 20 additions & 0 deletions src/main/scala/com/gvolpe/typed/actor/SimpleAkkaActor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.gvolpe.typed.actor

import akka.actor.{Actor, ActorSystem, Props}
import com.gvolpe.typed.actor.SimpleAkkaActor.{SimpleMessageOne, SimpleMessageTwo}

object SimpleAkkaActor {
sealed trait SimpleMessage
case class SimpleMessageOne(v: String) extends SimpleMessage
case class SimpleMessageTwo(v: String) extends SimpleMessage

def props(implicit s: ActorSystem) = s.actorOf(Props[SimpleAkkaActor])
}

class SimpleAkkaActor extends Actor {
override def receive: Receive = {
case one: SimpleMessageOne => println(s"received: $one")
case two: SimpleMessageTwo => println(s"received: $two")
case _ => println("Message not recognized!")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ package com.gvolpe.typed.actor

import akka.actor.{Actor, ActorSystem}
import de.knutwalker.akka.typed._
import com.gvolpe.typed.actor.TypedActorExample._
import com.gvolpe.typed.actor.SimpleTypedActor._

object TypedActorExample {
object SimpleTypedActor {
sealed trait MyMessage
case class Foo(foo: String) extends MyMessage
case class Bar(bar: String) extends MyMessage

def props(implicit s: ActorSystem) = ActorOf(Props[MyMessage, TypedActorExample], name = "typed-actor")
def props(implicit s: ActorSystem) = ActorOf(Props[MyMessage, SimpleTypedActor], name = "typed-actor")
}

class TypedActorExample extends Actor {
class SimpleTypedActor extends Actor {
override def receive: Receive = {
case Foo(foo) => println(s"received a Foo: $foo")
case Bar(bar) => println(s"received a Bar: $bar")
Expand Down
23 changes: 23 additions & 0 deletions src/main/scala/com/gvolpe/typed/actor/StrictTypedActor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.gvolpe.typed.actor

import akka.actor.ActorSystem
import com.gvolpe.typed.actor.StrictTypedActor._
import de.knutwalker.akka.typed._

object StrictTypedActor {
sealed trait StrictMessage
case object StrictOne extends StrictMessage
case object StrictTwo extends StrictMessage

case object NotStrict

def props(implicit s: ActorSystem) = ActorOf(Props[StrictMessage, StrictTypedActor], name = "StrictTypedActor")
}

class StrictTypedActor extends TypedActor.Of[StrictMessage] {
override def typedReceive: TypedReceive = {
case StrictOne => println(s"received StrictOne at $typedSelf")
case StrictTwo => println(s"received StrictTwo at $typedSelf")
// case NotStrict => println(s"this does not compile!")
}
}
29 changes: 29 additions & 0 deletions src/main/scala/com/gvolpe/typed/actor/StrictUnionTypedActor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.gvolpe.typed.actor

import akka.actor.ActorSystem
import com.gvolpe.typed.actor.StrictUnionTypedActor._
import de.knutwalker.akka.typed._

object StrictUnionTypedActor {
case class Foo()
case class Bar()
case class Baz()

// Message type derivation using PropsFor (only for typed actor)
def props(implicit s: ActorSystem) = ActorOf(PropsFor[StrictUnionTypedActor]).or[Bar].or[Baz]
}

// NOTE: It doesn't allow case objects as types
class StrictUnionTypedActor extends TypedActor.Of[Foo | Bar | Baz] {
override def typedReceive: TypedReceive = TotalUnion
.on[Foo]{case f:Foo => println(s"received $f")}
.on[Bar]{case b:Bar => println(s"received $b")}
.on[Baz]{case b:Baz => println(s"received $b")}
.apply

// NOTE: This won't compile because it fails on type-check exhaustiveness
// override def typedReceive: TypedReceive = TotalUnion
// .on[Foo]{case f:Foo => println(s"received $f")}
// .on[Baz]{case b:Baz => println(s"received $b")}
// .apply
}
21 changes: 21 additions & 0 deletions src/main/scala/com/gvolpe/typed/actor/UnionTypedActor.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.gvolpe.typed.actor

import akka.actor.{Actor, ActorSystem}
import de.knutwalker.akka.typed._
import com.gvolpe.typed.actor.UnionTypedActor._

object UnionTypedActor {
case class SampleOne(n: Int)
case class SampleTwo(v: String)
case class SampleThree(b: Boolean)

def props(implicit s: ActorSystem) = ActorOf(Props[SampleOne, UnionTypedActor]).or[SampleTwo].or[SampleThree]
}

class UnionTypedActor extends Actor {
override def receive: Receive = {
case one: SampleOne => println(s"received: $one")
case two: SampleTwo => println(s"received: $two")
case three: SampleThree => println(s"received: $three")
}
}

0 comments on commit 2a76064

Please sign in to comment.