=rem #3870 Stop re-delivery of system messages when watching non-existing sys

* We don't know the UID so we can't quarantine, but we can stop the endpoint
  writer and drop outstanding system messages
This commit is contained in:
Patrik Nordwall 2014-02-13 11:27:40 +01:00
parent f1edf78979
commit aa6bdd197e
9 changed files with 62 additions and 25 deletions

View file

@ -417,9 +417,10 @@ private[akka] class RemoteActorRefProvider(
/**
* Marks a remote system as out of sync and prevents reconnects until the quarantine timeout elapses.
* @param address Address of the remote system to be quarantined
* @param uid UID of the remote system
* @param uid UID of the remote system, if the uid is not defined it will not be a strong quarantine but
* the current endpoint writer will be stopped (dropping system messages) and the address will be gated
*/
def quarantine(address: Address, uid: Int): Unit = transport.quarantine(address: Address, uid: Int)
def quarantine(address: Address, uid: Option[Int]): Unit = transport.quarantine(address, uid)
/**
* INTERNAL API

View file

@ -85,9 +85,10 @@ private[akka] abstract class RemoteTransport(val system: ExtendedActorSystem, va
/**
* Marks a remote system as out of sync and prevents reconnects until the quarantine timeout elapses.
* @param address Address of the remote system to be quarantined
* @param uid UID of the remote system
* @param uid UID of the remote system, if the uid is not defined it will not be a strong quarantine but
* the current endpoint writer will be stopped (dropping system messages) and the address will be gated
*/
def quarantine(address: Address, uid: Int): Unit
def quarantine(address: Address, uid: Option[Int]): Unit
/**
* When this method returns true, some functionality will be turned off for security purposes.

View file

@ -164,7 +164,7 @@ private[akka] class RemoteWatcher(
watchingNodes foreach { a
if (!unreachable(a) && !failureDetector.isAvailable(a)) {
log.warning("Detected unreachable: [{}]", a)
addressUids.get(a) foreach { uid quarantine(a, uid) }
quarantine(a, addressUids.get(a))
publishAddressTerminated(a)
unreachable += a
}
@ -173,7 +173,7 @@ private[akka] class RemoteWatcher(
def publishAddressTerminated(address: Address): Unit =
context.system.eventStream.publish(AddressTerminated(address))
def quarantine(address: Address, uid: Int): Unit =
def quarantine(address: Address, uid: Option[Int]): Unit =
remoteProvider.quarantine(address, uid)
def rewatchRemote(watchee: ActorRef, watcher: ActorRef): Unit =

View file

@ -211,7 +211,7 @@ private[remote] class Remoting(_system: ExtendedActorSystem, _provider: RemoteAc
case None throw new RemoteTransportExceptionNoStackTrace("Attempted to send management command but Remoting is not running.", null)
}
override def quarantine(remoteAddress: Address, uid: Int): Unit = endpointManager match {
override def quarantine(remoteAddress: Address, uid: Option[Int]): Unit = endpointManager match {
case Some(manager) manager ! Quarantine(remoteAddress, uid)
case _ throw new RemoteTransportExceptionNoStackTrace(
s"Attempted to quarantine address [$remoteAddress] with uid [$uid] but Remoting is not running", null)
@ -244,7 +244,7 @@ private[remote] object EndpointManager {
// acknowledged delivery buffers
def seq = seqOpt.get
}
case class Quarantine(remoteAddress: Address, uid: Int) extends RemotingCommand
case class Quarantine(remoteAddress: Address, uid: Option[Int]) extends RemotingCommand
case class ManagementCommand(cmd: Any) extends RemotingCommand
case class ManagementCommandAck(status: Boolean)
@ -479,19 +479,28 @@ private[remote] class EndpointManager(conf: Config, log: LoggingAdapter) extends
}
Future.fold(allStatuses)(true)(_ && _) map ManagementCommandAck pipeTo sender()
case Quarantine(address, uid)
case Quarantine(address, uidOption)
// Stop writers
endpoints.writableEndpointWithPolicyFor(address) match {
case Some(Pass(endpoint)) context.stop(endpoint)
case _ // nothing to stop
case Some(Pass(endpoint))
context.stop(endpoint)
if (uidOption.isEmpty) {
log.warning("Association to [{}] with unknown UID is reported as quarantined, but " +
"address cannot be quarantined without knowing the UID, gating instead for {} ms.",
address, settings.RetryGateClosedFor.toMillis)
endpoints.markAsFailed(endpoint, Deadline.now + settings.RetryGateClosedFor)
}
case _ // nothing to stop
}
// Stop inbound read-only associations
endpoints.readOnlyEndpointFor(address) match {
case Some(endpoint) context.stop(endpoint)
case _ // nothing to stop
}
endpoints.markAsQuarantined(address, uid, Deadline.now + settings.QuarantineDuration)
eventPublisher.notifyListeners(QuarantinedEvent(address, uid))
uidOption foreach { uid
endpoints.markAsQuarantined(address, uid, Deadline.now + settings.QuarantineDuration)
eventPublisher.notifyListeners(QuarantinedEvent(address, uid))
}
case s @ Send(message, senderOption, recipientRef, _)
val recipientAddress = recipientRef.path.address