pekko/akka-camel/src/main/scala/akka/camel/internal/ActivationTracker.scala

117 lines
4.1 KiB
Scala
Raw Normal View History

/**
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.camel.internal
import akka.actor._
import collection.mutable.WeakHashMap
2012-03-18 10:46:08 +01:00
import akka.camel._
import internal.ActivationProtocol._
/**
2012-03-18 10:46:08 +01:00
* For internal use only. An actor that tracks activation and de-activation of endpoints.
*/
private[akka] final class ActivationTracker extends Actor with ActorLogging {
val activations = new WeakHashMap[ActorRef, ActivationStateMachine]
/**
* A state machine that keeps track of the endpoint activation status of an actor.
*/
class ActivationStateMachine {
type State = PartialFunction[ActivationMessage, Unit]
var receive: State = notActivated()
/**
* Not activated state
* @return a partial function that handles messages in the 'not activated' state
*/
def notActivated(): State = {
var awaitingActivation = List[ActorRef]()
var awaitingDeActivation = List[ActorRef]()
{
case AwaitActivation(ref) awaitingActivation ::= sender
case AwaitDeActivation(ref) awaitingDeActivation ::= sender
case msg @ EndpointActivated(ref)
awaitingActivation.foreach(_ ! msg)
receive = activated(awaitingDeActivation)
case EndpointFailedToActivate(ref, cause)
awaitingActivation.foreach(_ ! EndpointFailedToActivate(ref, cause))
receive = failedToActivate(cause)
}
}
/**
* Activated state.
* @param currentAwaitingDeActivation the current <code>ActorRef</code>s awaiting de-activation
* @return a partial function that handles messages in the 'activated' state
*/
def activated(currentAwaitingDeActivation: List[ActorRef]): State = {
var awaitingDeActivation = currentAwaitingDeActivation
{
case AwaitActivation(ref) sender ! EndpointActivated(ref)
case AwaitDeActivation(ref) awaitingDeActivation ::= sender
case msg @ EndpointDeActivated(ref)
awaitingDeActivation foreach (_ ! msg)
receive = deactivated
case msg @ EndpointFailedToDeActivate(ref, cause)
awaitingDeActivation foreach (_ ! msg)
receive = failedToDeActivate(cause)
}
}
/**
* De-activated state
* @return a partial function that handles messages in the 'de-activated' state
*/
def deactivated: State = {
case AwaitActivation(ref) sender ! EndpointActivated(ref)
case AwaitDeActivation(ref) sender ! EndpointDeActivated(ref)
}
/**
* Failed to activate state
* @param cause the cause for the failure
* @return a partial function that handles messages in 'failed to activate' state
*/
def failedToActivate(cause: Throwable): State = {
case AwaitActivation(ref) sender ! EndpointFailedToActivate(ref, cause)
case AwaitDeActivation(ref) sender ! EndpointFailedToActivate(ref, cause)
}
/**
* Failed to de-activate state
* @param cause the cause for the failure
* @return a partial function that handles messages in 'failed to de-activate' state
*/
def failedToDeActivate(cause: Throwable): State = {
case AwaitActivation(ref) sender ! EndpointActivated(ref)
case AwaitDeActivation(ref) sender ! EndpointFailedToDeActivate(ref, cause)
}
}
override def receive = {
case msg @ ActivationMessage(ref)
2012-05-23 15:17:49 +02:00
(activations.getOrElseUpdate(ref, new ActivationStateMachine).receive orElse logStateWarning(ref))(msg)
}
2012-05-23 15:17:49 +02:00
private[this] def logStateWarning(actorRef: ActorRef): Receive =
{ case msg log.warning("Message [{}] not expected in current state of actor [{}]", msg, actorRef) }
}
2012-03-18 10:46:08 +01:00
/**
* For internal use only. A request message to the ActivationTracker for the status of activation.
* @param ref the actorRef
*/
private[camel] case class AwaitActivation(ref: ActorRef) extends ActivationMessage(ref)
2012-03-18 10:46:08 +01:00
/**
* For internal use only. A request message to the ActivationTracker for the status of de-activation.
* For internal use only.
* @param ref the actorRef
*/
private[camel] case class AwaitDeActivation(ref: ActorRef) extends ActivationMessage(ref)