handle serialization errors, #20324
This commit is contained in:
parent
e74e1da6cc
commit
aa2c4fe7bf
3 changed files with 142 additions and 25 deletions
|
|
@ -1,13 +1,16 @@
|
|||
package akka.remote.artery
|
||||
|
||||
import scala.util.control.NonFatal
|
||||
|
||||
import akka.actor.{ ActorRef, InternalActorRef }
|
||||
import akka.remote.EndpointManager.Send
|
||||
import akka.actor.ActorSystem
|
||||
import akka.actor.ExtendedActorSystem
|
||||
import akka.remote.{ MessageSerializer, UniqueAddress }
|
||||
import akka.remote.EndpointManager.Send
|
||||
import akka.remote.artery.SystemMessageDelivery.SystemMessageEnvelope
|
||||
import akka.serialization.{ Serialization, SerializationExtension }
|
||||
import akka.stream._
|
||||
import akka.stream.stage.{ GraphStage, GraphStageLogic, InHandler, OutHandler }
|
||||
import akka.actor.ActorSystem
|
||||
import akka.actor.ExtendedActorSystem
|
||||
|
||||
// TODO: Long UID
|
||||
class Encoder(
|
||||
|
|
@ -22,7 +25,7 @@ class Encoder(
|
|||
val shape: FlowShape[Send, EnvelopeBuffer] = FlowShape(in, out)
|
||||
|
||||
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic =
|
||||
new GraphStageLogic(shape) with InHandler with OutHandler {
|
||||
new GraphStageLogic(shape) with InHandler with OutHandler with StageLogging {
|
||||
|
||||
private val headerBuilder = HeaderBuilder(compressionTable)
|
||||
headerBuilder.version = ArteryTransport.Version
|
||||
|
|
@ -35,6 +38,8 @@ class Encoder(
|
|||
private val senderCache = new java.util.HashMap[ActorRef, String]
|
||||
private var recipientCache = new java.util.HashMap[ActorRef, String]
|
||||
|
||||
override protected def logSource = classOf[Encoder]
|
||||
|
||||
override def onPush(): Unit = {
|
||||
val send = grab(in)
|
||||
val envelope = pool.acquire()
|
||||
|
|
@ -69,18 +74,31 @@ class Encoder(
|
|||
headerBuilder.senderActorRef = noSender
|
||||
}
|
||||
|
||||
// avoiding currentTransportInformation.withValue due to thunk allocation
|
||||
val oldValue = Serialization.currentTransportInformation.value
|
||||
try {
|
||||
Serialization.currentTransportInformation.value = serializationInfo
|
||||
MessageSerializer.serializeForArtery(serialization, send.message.asInstanceOf[AnyRef], headerBuilder, envelope)
|
||||
} finally
|
||||
Serialization.currentTransportInformation.value = oldValue
|
||||
// avoiding currentTransportInformation.withValue due to thunk allocation
|
||||
val oldValue = Serialization.currentTransportInformation.value
|
||||
try {
|
||||
Serialization.currentTransportInformation.value = serializationInfo
|
||||
MessageSerializer.serializeForArtery(serialization, send.message.asInstanceOf[AnyRef], headerBuilder, envelope)
|
||||
} finally
|
||||
Serialization.currentTransportInformation.value = oldValue
|
||||
|
||||
//println(s"${headerBuilder.senderActorRef} --> ${headerBuilder.recipientActorRef} ${headerBuilder.classManifest}")
|
||||
envelope.byteBuffer.flip()
|
||||
push(out, envelope)
|
||||
|
||||
} catch {
|
||||
case NonFatal(e) ⇒
|
||||
pool.release(envelope)
|
||||
send.message match {
|
||||
case _: SystemMessageEnvelope ⇒
|
||||
log.error(e, "Failed to serialize system message [{}].", send.message.getClass.getName)
|
||||
throw e
|
||||
case _ ⇒
|
||||
log.error(e, "Failed to serialize message [{}].", send.message.getClass.getName)
|
||||
pull(in)
|
||||
}
|
||||
}
|
||||
|
||||
envelope.byteBuffer.flip()
|
||||
push(out, envelope)
|
||||
}
|
||||
|
||||
override def onPull(): Unit = pull(in)
|
||||
|
|
@ -100,7 +118,7 @@ class Decoder(
|
|||
val shape: FlowShape[EnvelopeBuffer, InboundEnvelope] = FlowShape(in, out)
|
||||
|
||||
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic =
|
||||
new GraphStageLogic(shape) with InHandler with OutHandler {
|
||||
new GraphStageLogic(shape) with InHandler with OutHandler with StageLogging {
|
||||
private val localAddress = uniqueLocalAddress.address
|
||||
private val headerBuilder = HeaderBuilder(compressionTable)
|
||||
private val serialization = SerializationExtension(system)
|
||||
|
|
@ -108,12 +126,12 @@ class Decoder(
|
|||
private val recipientCache = new java.util.HashMap[String, InternalActorRef]
|
||||
private val senderCache = new java.util.HashMap[String, Option[ActorRef]]
|
||||
|
||||
override protected def logSource = classOf[Decoder]
|
||||
|
||||
override def onPush(): Unit = {
|
||||
val envelope = grab(in)
|
||||
envelope.parseHeader(headerBuilder)
|
||||
|
||||
//println(s"${headerBuilder.recipientActorRef} <-- ${headerBuilder.senderActorRef} ${headerBuilder.classManifest}")
|
||||
|
||||
// FIXME: Instead of using Strings, the headerBuilder should automatically return cached ActorRef instances
|
||||
// in case of compression is enabled
|
||||
// FIXME: Is localAddress really needed?
|
||||
|
|
@ -140,15 +158,26 @@ class Decoder(
|
|||
case refOpt ⇒ refOpt
|
||||
}
|
||||
|
||||
val decoded = InboundEnvelope(
|
||||
recipient,
|
||||
localAddress, // FIXME: Is this needed anymore? What should we do here?
|
||||
MessageSerializer.deserializeForArtery(system, serialization, headerBuilder, envelope),
|
||||
senderOption, // FIXME: No need for an option, decode simply to deadLetters instead
|
||||
UniqueAddress(senderOption.get.path.address, headerBuilder.uid)) // FIXME see issue #20568
|
||||
try {
|
||||
val deserializedMessage = MessageSerializer.deserializeForArtery(
|
||||
system, serialization, headerBuilder, envelope)
|
||||
|
||||
pool.release(envelope)
|
||||
push(out, decoded)
|
||||
val decoded = InboundEnvelope(
|
||||
recipient,
|
||||
localAddress, // FIXME: Is this needed anymore? What should we do here?
|
||||
deserializedMessage,
|
||||
senderOption, // FIXME: No need for an option, decode simply to deadLetters instead
|
||||
UniqueAddress(senderOption.get.path.address, headerBuilder.uid)) // FIXME see issue #20568
|
||||
|
||||
push(out, decoded)
|
||||
} catch {
|
||||
case NonFatal(e) ⇒
|
||||
log.warning("Failed to deserialize message with serializer id [{}] and manifest [{}]. {}",
|
||||
headerBuilder.serializer, headerBuilder.classManifest, e.getMessage)
|
||||
pull(in)
|
||||
} finally {
|
||||
pool.release(envelope)
|
||||
}
|
||||
}
|
||||
|
||||
override def onPull(): Unit = pull(in)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue