+str #24229 move SinkRef / SourceRef to akka.stream

+str #24229 remove protobuf changes, which do not need to be made in this PR

docs

moved things

config object

subscription timeout confifmed working, also, attributes

document attributes for sub timeout

tests for the source also failing when it should

additional demand test

implemented protection from materializing "in cycles"; would be nice in
types but that breaks the niceness of use of the types
SinkRef/SourceRef...

cleanup

no idle timeout built in, can use the Timeout stages

more docs

simplest change to prevent exposing SinkRef => SourceRef => SinkRef cycle

Things to decide:
 * is it ok to require using `getSource` / `getSink` as Java API, is there better naming?
 * where should the constructors go? I'd say just in regular javadsl/scaladsl `Source`/ `Sink` objects

move constructors to {javadsl,scaladsl}.{Source,Sink} companion objects

Remove now useless "canMaterialize" field

Separate stage (implementation) from ref (wrapped actor ref) to make it clearer what is serialized

Clarify that partner refs are not optional in on-the-wire interfaces

minor cleanup in SourceRefStage

Renamed the stages but questionable if that really helps ;)

cleanups, better docs

cleanup, fix docs compilation

fix mima

got rid of Futures in the materialized values of stream refs
This commit is contained in:
Konrad `ktoso` Malawski 2018-01-04 17:21:47 +01:00
parent bc6861f7e4
commit 7c75abbf7e
42 changed files with 2834 additions and 4386 deletions

View file

@ -0,0 +1,187 @@
/**
* Copyright (C) 2018 Lightbend Inc. <http://www.lightbend.com>
*/
package akka.stream.serialization
import akka.protobuf.ByteString
import akka.actor.ExtendedActorSystem
import akka.annotation.InternalApi
import akka.serialization.{ BaseSerializer, Serialization, SerializationExtension, SerializerWithStringManifest }
import akka.stream.StreamRefMessages
import akka.stream.impl.streamref._
import scala.concurrent.duration._
import scala.concurrent.Await
/** INTERNAL API */
@InternalApi
private[akka] final class StreamRefSerializer(val system: ExtendedActorSystem) extends SerializerWithStringManifest
with BaseSerializer {
private[this] lazy val serialization = SerializationExtension(system)
private[this] val SequencedOnNextManifest = "A"
private[this] val CumulativeDemandManifest = "B"
private[this] val RemoteSinkFailureManifest = "C"
private[this] val RemoteSinkCompletedManifest = "D"
private[this] val SourceRefManifest = "E"
private[this] val SinkRefManifest = "F"
private[this] val OnSubscribeHandshakeManifest = "G"
override def manifest(o: AnyRef): String = o match {
// protocol
case _: StreamRefsProtocol.SequencedOnNext[_] SequencedOnNextManifest
case _: StreamRefsProtocol.CumulativeDemand CumulativeDemandManifest
// handshake
case _: StreamRefsProtocol.OnSubscribeHandshake OnSubscribeHandshakeManifest
// completion
case _: StreamRefsProtocol.RemoteStreamFailure RemoteSinkFailureManifest
case _: StreamRefsProtocol.RemoteStreamCompleted RemoteSinkCompletedManifest
// refs
case _: SourceRefImpl[_] SourceRefManifest
case _: MaterializedSourceRef[_] SourceRefManifest
case _: SinkRefImpl[_] SinkRefManifest
case _: MaterializedSinkRef[_] SinkRefManifest
}
override def toBinary(o: AnyRef): Array[Byte] = o match {
// protocol
case o: StreamRefsProtocol.SequencedOnNext[_] serializeSequencedOnNext(o).toByteArray
case d: StreamRefsProtocol.CumulativeDemand serializeCumulativeDemand(d).toByteArray
// handshake
case h: StreamRefsProtocol.OnSubscribeHandshake serializeOnSubscribeHandshake(h).toByteArray
// termination
case d: StreamRefsProtocol.RemoteStreamFailure serializeRemoteSinkFailure(d).toByteArray
case d: StreamRefsProtocol.RemoteStreamCompleted serializeRemoteSinkCompleted(d).toByteArray
// refs
case ref: SinkRefImpl[_] serializeSinkRef(ref).toByteArray
case ref: MaterializedSinkRef[_] serializeSinkRef(Await.result(ref.futureSink, 100.millis)).toByteArray
case ref: SourceRefImpl[_] serializeSourceRef(ref).toByteArray
case ref: MaterializedSourceRef[_] serializeSourceRef(Await.result(ref.futureSource, 100.millis)).toByteArray
}
override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = manifest match {
// protocol
case OnSubscribeHandshakeManifest deserializeOnSubscribeHandshake(bytes)
case SequencedOnNextManifest deserializeSequencedOnNext(bytes)
case CumulativeDemandManifest deserializeCumulativeDemand(bytes)
case RemoteSinkCompletedManifest deserializeRemoteStreamCompleted(bytes)
case RemoteSinkFailureManifest deserializeRemoteStreamFailure(bytes)
// refs
case SinkRefManifest deserializeSinkRef(bytes)
case SourceRefManifest deserializeSourceRef(bytes)
}
// -----
private def serializeCumulativeDemand(d: StreamRefsProtocol.CumulativeDemand): StreamRefMessages.CumulativeDemand = {
StreamRefMessages.CumulativeDemand.newBuilder()
.setSeqNr(d.seqNr)
.build()
}
private def serializeRemoteSinkFailure(d: StreamRefsProtocol.RemoteStreamFailure): StreamRefMessages.RemoteStreamFailure = {
StreamRefMessages.RemoteStreamFailure.newBuilder()
.setCause(ByteString.copyFrom(d.msg.getBytes))
.build()
}
private def serializeRemoteSinkCompleted(d: StreamRefsProtocol.RemoteStreamCompleted): StreamRefMessages.RemoteStreamCompleted = {
StreamRefMessages.RemoteStreamCompleted.newBuilder()
.setSeqNr(d.seqNr)
.build()
}
private def serializeOnSubscribeHandshake(o: StreamRefsProtocol.OnSubscribeHandshake): StreamRefMessages.OnSubscribeHandshake = {
StreamRefMessages.OnSubscribeHandshake.newBuilder()
.setTargetRef(StreamRefMessages.ActorRef.newBuilder()
.setPath(Serialization.serializedActorPath(o.targetRef)))
.build()
}
private def serializeSequencedOnNext(o: StreamRefsProtocol.SequencedOnNext[_]) = {
val p = o.payload.asInstanceOf[AnyRef]
val msgSerializer = serialization.findSerializerFor(p)
val payloadBuilder = StreamRefMessages.Payload.newBuilder()
.setEnclosedMessage(ByteString.copyFrom(msgSerializer.toBinary(p)))
.setSerializerId(msgSerializer.identifier)
msgSerializer match {
case ser2: SerializerWithStringManifest
val manifest = ser2.manifest(p)
if (manifest != "")
payloadBuilder.setMessageManifest(ByteString.copyFromUtf8(manifest))
case _
if (msgSerializer.includeManifest)
payloadBuilder.setMessageManifest(ByteString.copyFromUtf8(p.getClass.getName))
}
StreamRefMessages.SequencedOnNext.newBuilder()
.setSeqNr(o.seqNr)
.setPayload(payloadBuilder.build())
.build()
}
private def serializeSinkRef(sink: SinkRefImpl[_]): StreamRefMessages.SinkRef = {
StreamRefMessages.SinkRef.newBuilder()
.setTargetRef(StreamRefMessages.ActorRef.newBuilder()
.setPath(Serialization.serializedActorPath(sink.initialPartnerRef)))
.build()
}
private def serializeSourceRef(source: SourceRefImpl[_]): StreamRefMessages.SourceRef = {
StreamRefMessages.SourceRef.newBuilder()
.setOriginRef(
StreamRefMessages.ActorRef.newBuilder()
.setPath(Serialization.serializedActorPath(source.initialPartnerRef)))
.build()
}
// ----------
private def deserializeOnSubscribeHandshake(bytes: Array[Byte]): StreamRefsProtocol.OnSubscribeHandshake = {
val handshake = StreamRefMessages.OnSubscribeHandshake.parseFrom(bytes)
val targetRef = serialization.system.provider.resolveActorRef(handshake.getTargetRef.getPath)
StreamRefsProtocol.OnSubscribeHandshake(targetRef)
}
private def deserializeSinkRef(bytes: Array[Byte]): SinkRefImpl[Any] = {
val ref = StreamRefMessages.SinkRef.parseFrom(bytes)
val initialTargetRef = serialization.system.provider.resolveActorRef(ref.getTargetRef.getPath)
SinkRefImpl[Any](initialTargetRef)
}
private def deserializeSourceRef(bytes: Array[Byte]): SourceRefImpl[Any] = {
val ref = StreamRefMessages.SourceRef.parseFrom(bytes)
val initialPartnerRef = serialization.system.provider.resolveActorRef(ref.getOriginRef.getPath)
SourceRefImpl[Any](initialPartnerRef)
}
private def deserializeSequencedOnNext(bytes: Array[Byte]): StreamRefsProtocol.SequencedOnNext[AnyRef] = {
val o = StreamRefMessages.SequencedOnNext.parseFrom(bytes)
val p = o.getPayload
val payload = serialization.deserialize(
p.getEnclosedMessage.toByteArray,
p.getSerializerId,
p.getMessageManifest.toStringUtf8
)
StreamRefsProtocol.SequencedOnNext(o.getSeqNr, payload.get)
}
private def deserializeCumulativeDemand(bytes: Array[Byte]): StreamRefsProtocol.CumulativeDemand = {
val d = StreamRefMessages.CumulativeDemand.parseFrom(bytes)
StreamRefsProtocol.CumulativeDemand(d.getSeqNr)
}
private def deserializeRemoteStreamCompleted(bytes: Array[Byte]): StreamRefsProtocol.RemoteStreamCompleted = {
val d = StreamRefMessages.RemoteStreamCompleted.parseFrom(bytes)
StreamRefsProtocol.RemoteStreamCompleted(d.getSeqNr)
}
private def deserializeRemoteStreamFailure(bytes: Array[Byte]): AnyRef = {
val d = StreamRefMessages.RemoteStreamFailure.parseFrom(bytes)
StreamRefsProtocol.RemoteStreamFailure(d.getCause.toStringUtf8)
}
}