Removing HotSwap and revertHotSwap
This commit is contained in:
parent
4803ba517c
commit
6cdb0126ad
6 changed files with 26 additions and 123 deletions
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 Actor’s 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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue