Removing HotSwap and revertHotSwap

This commit is contained in:
Viktor Klang 2011-12-08 14:44:18 +01:00
parent 4803ba517c
commit 6cdb0126ad
6 changed files with 26 additions and 123 deletions

View file

@ -11,15 +11,6 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
"An Actor" must {
"be able to hotswap its behavior with HotSwap(..)" in {
val a = system.actorOf(new Actor {
def receive = { case _ sender ! "default" }
})
a ! HotSwap(context { case _ context.sender ! "swapped" })
a ! "swapped"
expectMsg("swapped")
}
"be able to hotswap its behavior with become(..)" in {
val a = system.actorOf(new Actor {
def receive = {
@ -35,32 +26,6 @@ class HotSwapSpec extends AkkaSpec with ImplicitSender {
expectMsg("swapped")
}
"be able to revert hotswap its behavior with RevertHotSwap(..)" in {
val a = system.actorOf(new Actor {
def receive = {
case "init" sender ! "init"
}
})
a ! "init"
expectMsg("init")
a ! HotSwap(context { case "swapped" context.sender ! "swapped" })
a ! "swapped"
expectMsg("swapped")
a ! RevertHotSwap
a ! "init"
expectMsg("init")
// try to revert hotswap below the bottom of the stack
a ! RevertHotSwap
a ! "init"
expectMsg("init")
}
"be able to revert hotswap its behavior with unbecome" in {
val a = system.actorOf(new Actor {
def receive = {

View file

@ -29,29 +29,6 @@ class ReceiveTimeoutSpec extends AkkaSpec {
timeoutActor.stop()
}
"get timeout when swapped" in {
val timeoutLatch = TestLatch()
val timeoutActor = system.actorOf(new Actor {
context.receiveTimeout = Some(500 milliseconds)
protected def receive = {
case ReceiveTimeout timeoutLatch.open
}
})
timeoutLatch.await
val swappedLatch = TestLatch()
timeoutActor ! HotSwap(context {
case ReceiveTimeout swappedLatch.open
})
swappedLatch.await
timeoutActor.stop()
}
"reschedule timeout after regular receive" in {
val timeoutLatch = TestLatch()
case object Tick

View file

@ -13,7 +13,6 @@ import scala.collection.JavaConverters._
import java.util.Properties
import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.HotSwap
import akka.actor.UnhandledMessageException
import akka.actor.PoisonPill
import akka.actor.ActorSystemImpl
@ -77,22 +76,27 @@ class LoggingReceiveSpec extends WordSpec with BeforeAndAfterEach with BeforeAnd
ignoreMute(this)
system.eventStream.subscribe(testActor, classOf[Logging.Debug])
system.eventStream.subscribe(testActor, classOf[Logging.Error])
val r: Actor.Receive = {
case null
}
val actor = TestActorRef(new Actor {
def receive = LoggingReceive(this) {
case x
sender ! "x"
def switch: Actor.Receive = { case "becomenull" context.become(r, false) }
def receive = switch orElse LoggingReceive(this) {
case x sender ! "x"
}
})
val name = actor.path.toString
actor ! "buh"
within(1 second) {
expectMsg(Logging.Debug(name, "received handled message buh"))
expectMsg("x")
}
val r: Actor.Receive = {
case null
}
actor ! HotSwap(_ r, false)
actor ! "becomenull"
EventFilter[UnhandledMessageException](pattern = "does not handle", occurrences = 1) intercept {
within(500 millis) {
actor ! "bah"

View file

@ -30,29 +30,8 @@ sealed trait AutoReceivedMessage extends Serializable
trait PossiblyHarmful
case class HotSwap(code: ActorContext Actor.Receive, discardOld: Boolean = true) extends AutoReceivedMessage {
/**
* Java API
*/
def this(code: akka.japi.Function[ActorContext, Procedure[Any]], discardOld: Boolean) = {
this((context: ActorContext) {
val behavior = code(context)
val result: Actor.Receive = { case msg behavior(msg) }
result
}, discardOld)
}
/**
* Java API with default non-stacking behavior
*/
def this(code: akka.japi.Function[ActorContext, Procedure[Any]]) = this(code, true)
}
case class Failed(cause: Throwable) extends AutoReceivedMessage with PossiblyHarmful
case object RevertHotSwap extends AutoReceivedMessage with PossiblyHarmful
case object PoisonPill extends AutoReceivedMessage with PossiblyHarmful
case object Kill extends AutoReceivedMessage with PossiblyHarmful

View file

@ -510,14 +510,12 @@ private[akka] final class ActorCell(
if (system.settings.DebugAutoReceive) system.eventStream.publish(Debug(self.path.toString, "received AutoReceiveMessage " + msg))
msg.message match {
case HotSwap(code, discardOld) become(code(this), discardOld)
case RevertHotSwap unbecome()
case Failed(cause) handleFailure(sender, cause)
case Kill throw new ActorKilledException("Kill")
case PoisonPill self.stop()
case SelectParent(m) parent.tell(m, msg.sender)
case SelectChildName(name, m) if (childrenRefs contains name) childrenRefs(name).child.tell(m, msg.sender)
case SelectChildPattern(p, m) for (c children if p.matcher(c.path.name).matches) c.tell(m, msg.sender)
case Failed(cause) handleFailure(sender, cause)
case Kill throw new ActorKilledException("Kill")
case PoisonPill self.stop()
case SelectParent(m) parent.tell(m, msg.sender)
case SelectChildName(name, m) if (childrenRefs contains name) childrenRefs(name).child.tell(m, msg.sender)
case SelectChildPattern(p, m) for (c children if p.matcher(c.path.name).matches) c.tell(m, msg.sender)
}
}

View file

@ -414,10 +414,6 @@ object.
throw new RuntimeException("received timeout")
}
This mechanism also work for hotswapped receive functions. Every time a
``HotSwap`` is sent, the receive timeout is reset and rescheduled.
Starting actors
===============
@ -471,19 +467,18 @@ If the sender is a ``Future`` (e.g. the message is sent with ``?``), the
.. _Actor.HotSwap:
HotSwap
=======
Become/Unbecome
===============
Upgrade
-------
Akka supports hotswapping the Actors message loop (e.g. its implementation) at
runtime. There are two ways you can do that:
runtime.
* Send a ``HotSwap`` message to the Actor.
* Invoke the ``become`` method from within the Actor.
Both of these takes a ``ActorRef => PartialFunction[Any, Unit]`` that implements
Become takes a ``PartialFunction[Any, Unit]`` that implements
the new message handler. The hotswapped code is kept in a Stack which can be
pushed and popped.
@ -491,15 +486,7 @@ pushed and popped.
Please note that the actor will revert to its original behavior when restarted by its Supervisor.
To hotswap the Actor body using the ``HotSwap`` message:
.. code-block:: scala
actor ! HotSwap( context => {
case message => context reply "hotswapped body"
})
To hotswap the Actor using ``become``:
To hotswap the Actor behavior using ``become``:
.. code-block:: scala
@ -561,21 +548,14 @@ Downgrade
---------
Since the hotswapped code is pushed to a Stack you can downgrade the code as
well. There are two ways you can do that:
well.
* Send the Actor a ``RevertHotswap`` message
* Invoke the ``unbecome`` method from within the Actor.
Both of these will pop the Stack and replace the Actor's implementation with the
This will pop the Stack and replace the Actor's implementation with the
``PartialFunction[Any, Unit]`` that is at the top of the Stack.
Revert the Actor body using the ``RevertHotSwap`` message:
.. code-block:: scala
actor ! RevertHotSwap
Revert the Actor body using the ``unbecome`` method:
Here's how you use the ``unbecome`` method:
.. code-block:: scala