2018-10-29 17:19:37 +08:00
|
|
|
/*
|
2020-01-02 07:24:59 -05:00
|
|
|
* Copyright (C) 2009-2020 Lightbend Inc. <https://www.lightbend.com>
|
2015-08-17 16:11:52 +02:00
|
|
|
*/
|
2018-03-13 23:45:55 +09:00
|
|
|
|
2015-08-17 16:11:52 +02:00
|
|
|
package akka.cluster.sharding.protobuf
|
|
|
|
|
|
|
|
|
|
import java.io.{ ByteArrayInputStream, ByteArrayOutputStream }
|
|
|
|
|
import java.util.zip.GZIPInputStream
|
|
|
|
|
import java.util.zip.GZIPOutputStream
|
|
|
|
|
|
|
|
|
|
import scala.annotation.tailrec
|
2019-07-09 17:34:19 +02:00
|
|
|
import scala.concurrent.duration._
|
|
|
|
|
|
2019-05-24 08:11:50 +02:00
|
|
|
import akka.util.ccompat.JavaConverters._
|
2018-11-22 16:18:10 +01:00
|
|
|
import scala.collection.immutable
|
2019-07-09 17:34:19 +02:00
|
|
|
|
2015-08-17 16:11:52 +02:00
|
|
|
import akka.actor.ActorRef
|
|
|
|
|
import akka.actor.ExtendedActorSystem
|
|
|
|
|
import akka.cluster.sharding.Shard
|
|
|
|
|
import akka.cluster.sharding.ShardCoordinator
|
2019-02-09 15:25:39 +01:00
|
|
|
import akka.cluster.sharding.protobuf.msg.{ ClusterShardingMessages => sm }
|
2015-08-17 16:11:52 +02:00
|
|
|
import akka.serialization.BaseSerializer
|
|
|
|
|
import akka.serialization.Serialization
|
|
|
|
|
import akka.serialization.SerializerWithStringManifest
|
2019-08-15 16:43:19 +01:00
|
|
|
import akka.protobufv3.internal.MessageLite
|
2018-11-22 16:18:10 +01:00
|
|
|
import akka.util.ccompat._
|
2016-12-16 11:36:04 +01:00
|
|
|
import java.io.NotSerializableException
|
2015-08-17 16:11:52 +02:00
|
|
|
|
2019-07-09 17:34:19 +02:00
|
|
|
import akka.actor.Address
|
2018-09-21 12:09:11 +02:00
|
|
|
import akka.cluster.sharding.ShardRegion._
|
2019-07-09 17:34:19 +02:00
|
|
|
import akka.cluster.sharding.protobuf.msg.ClusterShardingMessages
|
2017-05-22 10:08:18 +02:00
|
|
|
|
2015-08-17 16:11:52 +02:00
|
|
|
/**
|
|
|
|
|
* INTERNAL API: Protobuf serializer of ClusterSharding messages.
|
|
|
|
|
*/
|
2019-04-05 14:56:33 +02:00
|
|
|
@ccompatUsedUntil213
|
2015-08-17 16:11:52 +02:00
|
|
|
private[akka] class ClusterShardingMessageSerializer(val system: ExtendedActorSystem)
|
2019-03-11 10:38:24 +01:00
|
|
|
extends SerializerWithStringManifest
|
|
|
|
|
with BaseSerializer {
|
2015-08-17 16:11:52 +02:00
|
|
|
import ShardCoordinator.Internal._
|
2020-02-26 10:32:28 -08:00
|
|
|
import Shard.{ CurrentShardState, GetCurrentShardState }
|
2015-09-23 11:24:39 +02:00
|
|
|
import Shard.{ GetShardStats, ShardStats }
|
2019-02-09 15:25:39 +01:00
|
|
|
import Shard.{ State => EntityState, EntityStarted, EntityStopped }
|
2015-08-17 16:11:52 +02:00
|
|
|
|
|
|
|
|
private final val BufferSize = 1024 * 4
|
|
|
|
|
|
|
|
|
|
private val CoordinatorStateManifest = "AA"
|
|
|
|
|
private val ShardRegionRegisteredManifest = "AB"
|
|
|
|
|
private val ShardRegionProxyRegisteredManifest = "AC"
|
|
|
|
|
private val ShardRegionTerminatedManifest = "AD"
|
|
|
|
|
private val ShardRegionProxyTerminatedManifest = "AE"
|
|
|
|
|
private val ShardHomeAllocatedManifest = "AF"
|
|
|
|
|
private val ShardHomeDeallocatedManifest = "AG"
|
|
|
|
|
|
|
|
|
|
private val RegisterManifest = "BA"
|
|
|
|
|
private val RegisterProxyManifest = "BB"
|
|
|
|
|
private val RegisterAckManifest = "BC"
|
|
|
|
|
private val GetShardHomeManifest = "BD"
|
|
|
|
|
private val ShardHomeManifest = "BE"
|
|
|
|
|
private val HostShardManifest = "BF"
|
|
|
|
|
private val ShardStartedManifest = "BG"
|
|
|
|
|
private val BeginHandOffManifest = "BH"
|
|
|
|
|
private val BeginHandOffAckManifest = "BI"
|
|
|
|
|
private val HandOffManifest = "BJ"
|
|
|
|
|
private val ShardStoppedManifest = "BK"
|
|
|
|
|
private val GracefulShutdownReqManifest = "BL"
|
|
|
|
|
|
|
|
|
|
private val EntityStateManifest = "CA"
|
|
|
|
|
private val EntityStartedManifest = "CB"
|
|
|
|
|
private val EntityStoppedManifest = "CD"
|
|
|
|
|
|
2017-05-22 10:08:18 +02:00
|
|
|
private val StartEntityManifest = "EA"
|
|
|
|
|
private val StartEntityAckManifest = "EB"
|
|
|
|
|
|
2015-09-23 11:24:39 +02:00
|
|
|
private val GetShardStatsManifest = "DA"
|
|
|
|
|
private val ShardStatsManifest = "DB"
|
2018-09-21 12:09:11 +02:00
|
|
|
private val GetShardRegionStatsManifest = "DC"
|
|
|
|
|
private val ShardRegionStatsManifest = "DD"
|
2019-07-09 17:34:19 +02:00
|
|
|
private val GetClusterShardingStatsManifest = "DE"
|
|
|
|
|
private val ClusterShardingStatsManifest = "DF"
|
|
|
|
|
private val GetCurrentRegionsManifest = "DG"
|
|
|
|
|
private val CurrentRegionsManifest = "DH"
|
2015-09-23 11:24:39 +02:00
|
|
|
|
2020-02-26 10:32:28 -08:00
|
|
|
private val GetCurrentShardStateManifest = "FA"
|
|
|
|
|
private val CurrentShardStateManifest = "FB"
|
|
|
|
|
private val GetShardRegionStateManifest = "FC"
|
|
|
|
|
private val ShardStateManifest = "FD"
|
|
|
|
|
private val CurrentShardRegionStateManifest = "FE"
|
|
|
|
|
|
2019-02-09 15:25:39 +01:00
|
|
|
private val fromBinaryMap = collection.immutable.HashMap[String, Array[Byte] => AnyRef](
|
|
|
|
|
EntityStateManifest -> entityStateFromBinary,
|
|
|
|
|
EntityStartedManifest -> entityStartedFromBinary,
|
|
|
|
|
EntityStoppedManifest -> entityStoppedFromBinary,
|
|
|
|
|
CoordinatorStateManifest -> coordinatorStateFromBinary,
|
2019-03-11 10:38:24 +01:00
|
|
|
ShardRegionRegisteredManifest -> { bytes =>
|
|
|
|
|
ShardRegionRegistered(actorRefMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
ShardRegionProxyRegisteredManifest -> { bytes =>
|
|
|
|
|
ShardRegionProxyRegistered(actorRefMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
ShardRegionTerminatedManifest -> { bytes =>
|
|
|
|
|
ShardRegionTerminated(actorRefMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
ShardRegionProxyTerminatedManifest -> { bytes =>
|
|
|
|
|
ShardRegionProxyTerminated(actorRefMessageFromBinary(bytes))
|
|
|
|
|
},
|
2019-02-09 15:25:39 +01:00
|
|
|
ShardHomeAllocatedManifest -> shardHomeAllocatedFromBinary,
|
2019-03-11 10:38:24 +01:00
|
|
|
ShardHomeDeallocatedManifest -> { bytes =>
|
|
|
|
|
ShardHomeDeallocated(shardIdMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
RegisterManifest -> { bytes =>
|
|
|
|
|
Register(actorRefMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
RegisterProxyManifest -> { bytes =>
|
|
|
|
|
RegisterProxy(actorRefMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
RegisterAckManifest -> { bytes =>
|
|
|
|
|
RegisterAck(actorRefMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
GetShardHomeManifest -> { bytes =>
|
|
|
|
|
GetShardHome(shardIdMessageFromBinary(bytes))
|
|
|
|
|
},
|
2019-02-09 15:25:39 +01:00
|
|
|
ShardHomeManifest -> shardHomeFromBinary,
|
2019-03-11 10:38:24 +01:00
|
|
|
HostShardManifest -> { bytes =>
|
|
|
|
|
HostShard(shardIdMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
ShardStartedManifest -> { bytes =>
|
|
|
|
|
ShardStarted(shardIdMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
BeginHandOffManifest -> { bytes =>
|
|
|
|
|
BeginHandOff(shardIdMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
BeginHandOffAckManifest -> { bytes =>
|
|
|
|
|
BeginHandOffAck(shardIdMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
HandOffManifest -> { bytes =>
|
|
|
|
|
HandOff(shardIdMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
ShardStoppedManifest -> { bytes =>
|
|
|
|
|
ShardStopped(shardIdMessageFromBinary(bytes))
|
|
|
|
|
},
|
|
|
|
|
GracefulShutdownReqManifest -> { bytes =>
|
|
|
|
|
GracefulShutdownReq(actorRefMessageFromBinary(bytes))
|
|
|
|
|
},
|
2019-04-05 14:56:33 +02:00
|
|
|
GetShardStatsManifest -> { _ =>
|
2019-03-11 10:38:24 +01:00
|
|
|
GetShardStats
|
|
|
|
|
},
|
|
|
|
|
ShardStatsManifest -> { bytes =>
|
|
|
|
|
shardStatsFromBinary(bytes)
|
|
|
|
|
},
|
2019-04-05 14:56:33 +02:00
|
|
|
GetShardRegionStatsManifest -> { _ =>
|
2019-03-11 10:38:24 +01:00
|
|
|
GetShardRegionStats
|
|
|
|
|
},
|
|
|
|
|
ShardRegionStatsManifest -> { bytes =>
|
|
|
|
|
shardRegionStatsFromBinary(bytes)
|
|
|
|
|
},
|
2019-07-09 17:34:19 +02:00
|
|
|
GetClusterShardingStatsManifest -> { bytes =>
|
|
|
|
|
getClusterShardingStatsFromBinary(bytes)
|
|
|
|
|
},
|
|
|
|
|
ClusterShardingStatsManifest -> { bytes =>
|
|
|
|
|
clusterShardingStatsFromBinary(bytes)
|
|
|
|
|
},
|
|
|
|
|
GetCurrentRegionsManifest -> { _ =>
|
|
|
|
|
GetCurrentRegions
|
|
|
|
|
},
|
|
|
|
|
CurrentRegionsManifest -> { bytes =>
|
|
|
|
|
currentRegionsFromBinary(bytes)
|
|
|
|
|
},
|
2019-02-09 15:25:39 +01:00
|
|
|
StartEntityManifest -> { startEntityFromBinary(_) },
|
2020-02-26 10:32:28 -08:00
|
|
|
StartEntityAckManifest -> { startEntityAckFromBinary(_) },
|
|
|
|
|
GetCurrentShardStateManifest -> { _ =>
|
|
|
|
|
GetCurrentShardState
|
|
|
|
|
},
|
|
|
|
|
CurrentShardStateManifest -> { bytes =>
|
|
|
|
|
currentShardStateFromBinary(bytes)
|
|
|
|
|
},
|
|
|
|
|
GetShardRegionStateManifest -> { _ =>
|
|
|
|
|
GetShardRegionState
|
|
|
|
|
},
|
|
|
|
|
ShardStateManifest -> { bytes =>
|
|
|
|
|
shardStateFromBinary(bytes)
|
|
|
|
|
},
|
|
|
|
|
CurrentShardRegionStateManifest -> { bytes =>
|
|
|
|
|
currentShardRegionStateFromBinary(bytes)
|
|
|
|
|
})
|
2015-08-17 16:11:52 +02:00
|
|
|
|
|
|
|
|
override def manifest(obj: AnyRef): String = obj match {
|
2019-03-11 10:38:24 +01:00
|
|
|
case _: EntityState => EntityStateManifest
|
|
|
|
|
case _: EntityStarted => EntityStartedManifest
|
|
|
|
|
case _: EntityStopped => EntityStoppedManifest
|
2019-02-09 15:25:39 +01:00
|
|
|
|
|
|
|
|
case _: State => CoordinatorStateManifest
|
|
|
|
|
case _: ShardRegionRegistered => ShardRegionRegisteredManifest
|
|
|
|
|
case _: ShardRegionProxyRegistered => ShardRegionProxyRegisteredManifest
|
|
|
|
|
case _: ShardRegionTerminated => ShardRegionTerminatedManifest
|
|
|
|
|
case _: ShardRegionProxyTerminated => ShardRegionProxyTerminatedManifest
|
|
|
|
|
case _: ShardHomeAllocated => ShardHomeAllocatedManifest
|
|
|
|
|
case _: ShardHomeDeallocated => ShardHomeDeallocatedManifest
|
|
|
|
|
|
2019-03-11 10:38:24 +01:00
|
|
|
case _: Register => RegisterManifest
|
|
|
|
|
case _: RegisterProxy => RegisterProxyManifest
|
|
|
|
|
case _: RegisterAck => RegisterAckManifest
|
|
|
|
|
case _: GetShardHome => GetShardHomeManifest
|
|
|
|
|
case _: ShardHome => ShardHomeManifest
|
|
|
|
|
case _: HostShard => HostShardManifest
|
|
|
|
|
case _: ShardStarted => ShardStartedManifest
|
|
|
|
|
case _: BeginHandOff => BeginHandOffManifest
|
|
|
|
|
case _: BeginHandOffAck => BeginHandOffAckManifest
|
|
|
|
|
case _: HandOff => HandOffManifest
|
|
|
|
|
case _: ShardStopped => ShardStoppedManifest
|
|
|
|
|
case _: GracefulShutdownReq => GracefulShutdownReqManifest
|
|
|
|
|
|
|
|
|
|
case _: StartEntity => StartEntityManifest
|
|
|
|
|
case _: StartEntityAck => StartEntityAckManifest
|
|
|
|
|
|
2019-07-09 17:34:19 +02:00
|
|
|
case GetShardStats => GetShardStatsManifest
|
|
|
|
|
case _: ShardStats => ShardStatsManifest
|
|
|
|
|
case GetShardRegionStats => GetShardRegionStatsManifest
|
|
|
|
|
case _: ShardRegionStats => ShardRegionStatsManifest
|
|
|
|
|
case _: GetClusterShardingStats => GetClusterShardingStatsManifest
|
|
|
|
|
case _: ClusterShardingStats => ClusterShardingStatsManifest
|
|
|
|
|
case GetCurrentRegions => GetCurrentRegionsManifest
|
|
|
|
|
case _: CurrentRegions => CurrentRegionsManifest
|
2020-02-26 10:32:28 -08:00
|
|
|
|
|
|
|
|
case GetCurrentShardState => GetCurrentShardStateManifest
|
|
|
|
|
case _: CurrentShardState => CurrentShardStateManifest
|
|
|
|
|
case GetShardRegionState => GetShardRegionStateManifest
|
|
|
|
|
case _: ShardState => ShardStateManifest
|
|
|
|
|
case _: CurrentShardRegionState => CurrentShardRegionStateManifest
|
|
|
|
|
|
2019-02-09 15:25:39 +01:00
|
|
|
case _ =>
|
2015-08-17 16:11:52 +02:00
|
|
|
throw new IllegalArgumentException(s"Can't serialize object of type ${obj.getClass} in [${getClass.getName}]")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def toBinary(obj: AnyRef): Array[Byte] = obj match {
|
2019-02-09 15:25:39 +01:00
|
|
|
case m: State => compress(coordinatorStateToProto(m))
|
|
|
|
|
case ShardRegionRegistered(ref) => actorRefMessageToProto(ref).toByteArray
|
|
|
|
|
case ShardRegionProxyRegistered(ref) => actorRefMessageToProto(ref).toByteArray
|
|
|
|
|
case ShardRegionTerminated(ref) => actorRefMessageToProto(ref).toByteArray
|
|
|
|
|
case ShardRegionProxyTerminated(ref) => actorRefMessageToProto(ref).toByteArray
|
|
|
|
|
case m: ShardHomeAllocated => shardHomeAllocatedToProto(m).toByteArray
|
|
|
|
|
case ShardHomeDeallocated(shardId) => shardIdMessageToProto(shardId).toByteArray
|
|
|
|
|
|
2019-03-11 10:38:24 +01:00
|
|
|
case Register(ref) => actorRefMessageToProto(ref).toByteArray
|
|
|
|
|
case RegisterProxy(ref) => actorRefMessageToProto(ref).toByteArray
|
|
|
|
|
case RegisterAck(ref) => actorRefMessageToProto(ref).toByteArray
|
|
|
|
|
case GetShardHome(shardId) => shardIdMessageToProto(shardId).toByteArray
|
|
|
|
|
case m: ShardHome => shardHomeToProto(m).toByteArray
|
|
|
|
|
case HostShard(shardId) => shardIdMessageToProto(shardId).toByteArray
|
|
|
|
|
case ShardStarted(shardId) => shardIdMessageToProto(shardId).toByteArray
|
|
|
|
|
case BeginHandOff(shardId) => shardIdMessageToProto(shardId).toByteArray
|
|
|
|
|
case BeginHandOffAck(shardId) => shardIdMessageToProto(shardId).toByteArray
|
|
|
|
|
case HandOff(shardId) => shardIdMessageToProto(shardId).toByteArray
|
|
|
|
|
case ShardStopped(shardId) => shardIdMessageToProto(shardId).toByteArray
|
2019-02-09 15:25:39 +01:00
|
|
|
case GracefulShutdownReq(ref) =>
|
2015-08-17 16:11:52 +02:00
|
|
|
actorRefMessageToProto(ref).toByteArray
|
|
|
|
|
|
2019-03-11 10:38:24 +01:00
|
|
|
case m: EntityState => entityStateToProto(m).toByteArray
|
|
|
|
|
case m: EntityStarted => entityStartedToProto(m).toByteArray
|
|
|
|
|
case m: EntityStopped => entityStoppedToProto(m).toByteArray
|
2017-05-22 10:08:18 +02:00
|
|
|
|
2019-03-11 10:38:24 +01:00
|
|
|
case s: StartEntity => startEntityToByteArray(s)
|
|
|
|
|
case s: StartEntityAck => startEntityAckToByteArray(s)
|
2015-09-23 11:24:39 +02:00
|
|
|
|
2019-07-09 17:34:19 +02:00
|
|
|
case GetShardStats => Array.emptyByteArray
|
|
|
|
|
case m: ShardStats => shardStatsToProto(m).toByteArray
|
|
|
|
|
case GetShardRegionStats => Array.emptyByteArray
|
|
|
|
|
case m: ShardRegionStats => shardRegionStatsToProto(m).toByteArray
|
|
|
|
|
case m: GetClusterShardingStats => getClusterShardingStatsToProto(m).toByteArray
|
|
|
|
|
case m: ClusterShardingStats => clusterShardingStatsToProto(m).toByteArray
|
|
|
|
|
case GetCurrentRegions => Array.emptyByteArray
|
|
|
|
|
case m: CurrentRegions => currentRegionsToProto(m).toByteArray
|
2015-09-23 11:24:39 +02:00
|
|
|
|
2020-02-26 10:32:28 -08:00
|
|
|
case GetCurrentShardState => Array.emptyByteArray
|
|
|
|
|
case m: CurrentShardState => currentShardStateToProto(m).toByteArray
|
|
|
|
|
case GetShardRegionState => Array.emptyByteArray
|
|
|
|
|
case m: ShardState => shardStateToProto(m).toByteArray
|
|
|
|
|
case m: CurrentShardRegionState => currentShardRegionStateToProto(m).toByteArray
|
|
|
|
|
|
2019-02-09 15:25:39 +01:00
|
|
|
case _ =>
|
2015-08-17 16:11:52 +02:00
|
|
|
throw new IllegalArgumentException(s"Can't serialize object of type ${obj.getClass} in [${getClass.getName}]")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef =
|
|
|
|
|
fromBinaryMap.get(manifest) match {
|
2019-02-09 15:25:39 +01:00
|
|
|
case Some(f) => f(bytes)
|
2019-03-11 10:38:24 +01:00
|
|
|
case None =>
|
|
|
|
|
throw new NotSerializableException(
|
|
|
|
|
s"Unimplemented deserialization of message with manifest [$manifest] in [${getClass.getName}]")
|
2015-08-17 16:11:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def coordinatorStateToProto(state: State): sm.CoordinatorState = {
|
|
|
|
|
val builder = sm.CoordinatorState.newBuilder()
|
|
|
|
|
|
|
|
|
|
state.shards.foreach {
|
2019-02-09 15:25:39 +01:00
|
|
|
case (shardId, regionRef) =>
|
2019-03-11 10:38:24 +01:00
|
|
|
val b = sm.CoordinatorState.ShardEntry
|
|
|
|
|
.newBuilder()
|
2015-08-17 16:11:52 +02:00
|
|
|
.setShardId(shardId)
|
|
|
|
|
.setRegionRef(Serialization.serializedActorPath(regionRef))
|
|
|
|
|
builder.addShards(b)
|
|
|
|
|
}
|
|
|
|
|
state.regions.foreach {
|
2019-02-09 15:25:39 +01:00
|
|
|
case (regionRef, _) => builder.addRegions(Serialization.serializedActorPath(regionRef))
|
2015-08-17 16:11:52 +02:00
|
|
|
}
|
2019-03-11 10:38:24 +01:00
|
|
|
state.regionProxies.foreach { ref =>
|
|
|
|
|
builder.addRegionProxies(Serialization.serializedActorPath(ref))
|
|
|
|
|
}
|
2015-08-17 16:11:52 +02:00
|
|
|
state.unallocatedShards.foreach { builder.addUnallocatedShards }
|
|
|
|
|
|
|
|
|
|
builder.build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def coordinatorStateFromBinary(bytes: Array[Byte]): State =
|
|
|
|
|
coordinatorStateFromProto(sm.CoordinatorState.parseFrom(decompress(bytes)))
|
|
|
|
|
|
|
|
|
|
private def coordinatorStateFromProto(state: sm.CoordinatorState): State = {
|
|
|
|
|
val shards: Map[String, ActorRef] =
|
2019-02-09 15:25:39 +01:00
|
|
|
state.getShardsList.asScala.toVector.iterator.map { entry =>
|
|
|
|
|
entry.getShardId -> resolveActorRef(entry.getRegionRef)
|
2018-11-22 16:18:10 +01:00
|
|
|
}.toMap
|
2015-08-17 16:11:52 +02:00
|
|
|
|
|
|
|
|
val regionsZero: Map[ActorRef, Vector[String]] =
|
2019-02-09 15:25:39 +01:00
|
|
|
state.getRegionsList.asScala.toVector.iterator.map(resolveActorRef(_) -> Vector.empty[String]).toMap
|
2015-08-17 16:11:52 +02:00
|
|
|
val regions: Map[ActorRef, Vector[String]] =
|
2019-03-11 10:38:24 +01:00
|
|
|
shards.foldLeft(regionsZero) {
|
|
|
|
|
case (acc, (shardId, regionRef)) => acc.updated(regionRef, acc(regionRef) :+ shardId)
|
|
|
|
|
}
|
2015-08-17 16:11:52 +02:00
|
|
|
|
2018-11-22 16:18:10 +01:00
|
|
|
val proxies: Set[ActorRef] = state.getRegionProxiesList.asScala.iterator.map { resolveActorRef }.to(immutable.Set)
|
2015-08-17 16:11:52 +02:00
|
|
|
val unallocatedShards: Set[String] = state.getUnallocatedShardsList.asScala.toSet
|
|
|
|
|
|
|
|
|
|
State(shards, regions, proxies, unallocatedShards)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def actorRefMessageToProto(ref: ActorRef): sm.ActorRefMessage =
|
|
|
|
|
sm.ActorRefMessage.newBuilder().setRef(Serialization.serializedActorPath(ref)).build()
|
|
|
|
|
|
|
|
|
|
private def actorRefMessageFromBinary(bytes: Array[Byte]): ActorRef =
|
|
|
|
|
resolveActorRef(sm.ActorRefMessage.parseFrom(bytes).getRef)
|
|
|
|
|
|
|
|
|
|
private def shardIdMessageToProto(shardId: String): sm.ShardIdMessage =
|
|
|
|
|
sm.ShardIdMessage.newBuilder().setShard(shardId).build()
|
|
|
|
|
|
|
|
|
|
private def shardIdMessageFromBinary(bytes: Array[Byte]): String =
|
|
|
|
|
sm.ShardIdMessage.parseFrom(bytes).getShard
|
|
|
|
|
|
|
|
|
|
private def shardHomeAllocatedToProto(evt: ShardHomeAllocated): sm.ShardHomeAllocated =
|
2019-03-11 10:38:24 +01:00
|
|
|
sm.ShardHomeAllocated
|
|
|
|
|
.newBuilder()
|
|
|
|
|
.setShard(evt.shard)
|
|
|
|
|
.setRegion(Serialization.serializedActorPath(evt.region))
|
|
|
|
|
.build()
|
2015-08-17 16:11:52 +02:00
|
|
|
|
|
|
|
|
private def shardHomeAllocatedFromBinary(bytes: Array[Byte]): ShardHomeAllocated = {
|
|
|
|
|
val m = sm.ShardHomeAllocated.parseFrom(bytes)
|
|
|
|
|
ShardHomeAllocated(m.getShard, resolveActorRef(m.getRegion))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def shardHomeToProto(m: ShardHome): sm.ShardHome =
|
2019-03-11 10:38:24 +01:00
|
|
|
sm.ShardHome.newBuilder().setShard(m.shard).setRegion(Serialization.serializedActorPath(m.ref)).build()
|
2015-08-17 16:11:52 +02:00
|
|
|
|
|
|
|
|
private def shardHomeFromBinary(bytes: Array[Byte]): ShardHome = {
|
|
|
|
|
val m = sm.ShardHome.parseFrom(bytes)
|
|
|
|
|
ShardHome(m.getShard, resolveActorRef(m.getRegion))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def entityStateToProto(m: EntityState): sm.EntityState = {
|
|
|
|
|
val b = sm.EntityState.newBuilder()
|
|
|
|
|
m.entities.foreach(b.addEntities)
|
|
|
|
|
b.build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def entityStateFromBinary(bytes: Array[Byte]): EntityState =
|
|
|
|
|
EntityState(sm.EntityState.parseFrom(bytes).getEntitiesList.asScala.toSet)
|
|
|
|
|
|
|
|
|
|
private def entityStartedToProto(evt: EntityStarted): sm.EntityStarted =
|
|
|
|
|
sm.EntityStarted.newBuilder().setEntityId(evt.entityId).build()
|
|
|
|
|
|
|
|
|
|
private def entityStartedFromBinary(bytes: Array[Byte]): EntityStarted =
|
|
|
|
|
EntityStarted(sm.EntityStarted.parseFrom(bytes).getEntityId)
|
|
|
|
|
|
|
|
|
|
private def entityStoppedToProto(evt: EntityStopped): sm.EntityStopped =
|
|
|
|
|
sm.EntityStopped.newBuilder().setEntityId(evt.entityId).build()
|
|
|
|
|
|
|
|
|
|
private def entityStoppedFromBinary(bytes: Array[Byte]): EntityStopped =
|
|
|
|
|
EntityStopped(sm.EntityStopped.parseFrom(bytes).getEntityId)
|
|
|
|
|
|
2015-09-23 11:24:39 +02:00
|
|
|
private def shardStatsToProto(evt: ShardStats): sm.ShardStats =
|
|
|
|
|
sm.ShardStats.newBuilder().setShard(evt.shardId).setEntityCount(evt.entityCount).build()
|
|
|
|
|
|
|
|
|
|
private def shardStatsFromBinary(bytes: Array[Byte]): ShardStats = {
|
|
|
|
|
val parsed = sm.ShardStats.parseFrom(bytes)
|
|
|
|
|
ShardStats(parsed.getShard, parsed.getEntityCount)
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-21 12:09:11 +02:00
|
|
|
private def shardRegionStatsToProto(evt: ShardRegionStats): sm.ShardRegionStats = {
|
|
|
|
|
val b = sm.ShardRegionStats.newBuilder()
|
|
|
|
|
evt.stats.foreach {
|
2019-02-09 15:25:39 +01:00
|
|
|
case (sid, no) =>
|
2018-09-21 12:09:11 +02:00
|
|
|
b.addStats(sm.MapFieldEntry.newBuilder().setKey(sid).setValue(no).build())
|
|
|
|
|
}
|
2019-07-25 08:00:34 -07:00
|
|
|
evt.failed.foreach { sid =>
|
|
|
|
|
b.addFailed(sid).build()
|
|
|
|
|
}
|
2018-09-21 12:09:11 +02:00
|
|
|
b.build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def shardRegionStatsFromBinary(bytes: Array[Byte]): ShardRegionStats = {
|
|
|
|
|
val parsed = sm.ShardRegionStats.parseFrom(bytes)
|
2019-07-09 17:34:19 +02:00
|
|
|
shardRegionStatsFromProto(parsed)
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-25 08:00:34 -07:00
|
|
|
private def shardRegionStatsFromProto(parsed: ClusterShardingMessages.ShardRegionStats): ShardRegionStats = {
|
2019-02-09 15:25:39 +01:00
|
|
|
val stats: Map[String, Int] = parsed.getStatsList.asScala.iterator.map(e => e.getKey -> e.getValue).toMap
|
2019-07-25 08:00:34 -07:00
|
|
|
val failed: Set[String] = parsed.getFailedList.asScala.toSet
|
|
|
|
|
ShardRegionStats(stats, failed)
|
2018-09-21 12:09:11 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-09 17:34:19 +02:00
|
|
|
private def clusterShardingStatsToProto(evt: ClusterShardingStats): sm.ClusterShardingStats = {
|
|
|
|
|
val b = sm.ClusterShardingStats.newBuilder()
|
|
|
|
|
evt.regions.foreach {
|
|
|
|
|
case (address, shardRegionStats) =>
|
|
|
|
|
b.addStats(
|
|
|
|
|
sm.ClusterShardingStatsEntry
|
|
|
|
|
.newBuilder()
|
|
|
|
|
.setAddress(serializeAddress(address))
|
|
|
|
|
.setStats(shardRegionStatsToProto(shardRegionStats))
|
|
|
|
|
.build())
|
|
|
|
|
}
|
|
|
|
|
b.build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def clusterShardingStatsFromBinary(bytes: Array[Byte]): ClusterShardingStats = {
|
|
|
|
|
val parsed = sm.ClusterShardingStats.parseFrom(bytes)
|
|
|
|
|
val stats: Map[Address, ShardRegionStats] =
|
|
|
|
|
parsed.getStatsList.asScala.iterator
|
|
|
|
|
.map(e => deserializeAddress(e.getAddress) -> shardRegionStatsFromProto(e.getStats))
|
|
|
|
|
.toMap
|
|
|
|
|
ClusterShardingStats(stats)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def getClusterShardingStatsToProto(evt: GetClusterShardingStats): sm.GetClusterShardingStats = {
|
|
|
|
|
sm.GetClusterShardingStats.newBuilder().setTimeoutNanos(evt.timeout.toNanos).build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def getClusterShardingStatsFromBinary(bytes: Array[Byte]): GetClusterShardingStats = {
|
|
|
|
|
val parsed = sm.GetClusterShardingStats.parseFrom(bytes)
|
|
|
|
|
GetClusterShardingStats(parsed.getTimeoutNanos.nanos)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def currentRegionsToProto(evt: CurrentRegions): sm.CurrentRegions = {
|
|
|
|
|
val b = sm.CurrentRegions.newBuilder()
|
|
|
|
|
evt.regions.foreach { address =>
|
|
|
|
|
b.addRegions(serializeAddress(address))
|
|
|
|
|
}
|
|
|
|
|
b.build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def currentRegionsFromBinary(bytes: Array[Byte]): CurrentRegions = {
|
|
|
|
|
val parsed = sm.CurrentRegions.parseFrom(bytes)
|
|
|
|
|
val regions: Set[Address] = parsed.getRegionsList.asScala.iterator.map(deserializeAddress).toSet
|
|
|
|
|
CurrentRegions(regions)
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-22 10:08:18 +02:00
|
|
|
private def startEntityToByteArray(s: StartEntity): Array[Byte] = {
|
|
|
|
|
val builder = sm.StartEntity.newBuilder()
|
|
|
|
|
builder.setEntityId(s.entityId)
|
|
|
|
|
builder.build().toByteArray
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def startEntityFromBinary(bytes: Array[Byte]): StartEntity = {
|
|
|
|
|
val se = sm.StartEntity.parseFrom(bytes)
|
|
|
|
|
StartEntity(se.getEntityId)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def startEntityAckToByteArray(s: StartEntityAck): Array[Byte] = {
|
|
|
|
|
val builder = sm.StartEntityAck.newBuilder()
|
|
|
|
|
builder.setEntityId(s.entityId)
|
|
|
|
|
builder.setShardId(s.shardId)
|
|
|
|
|
builder.build().toByteArray
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def startEntityAckFromBinary(bytes: Array[Byte]): StartEntityAck = {
|
|
|
|
|
val sea = sm.StartEntityAck.parseFrom(bytes)
|
|
|
|
|
StartEntityAck(sea.getEntityId, sea.getShardId)
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-26 10:32:28 -08:00
|
|
|
private def shardStateToProto(evt: ShardState): sm.ShardState = {
|
|
|
|
|
sm.ShardState.newBuilder().setShardId(evt.shardId).addAllEntityIds(evt.entityIds.asJava).build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def currentShardStateToProto(evt: CurrentShardState): sm.CurrentShardState = {
|
|
|
|
|
sm.CurrentShardState.newBuilder().setShardId(evt.shardId).addAllEntityIds(evt.entityIds.asJava).build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def currentShardStateFromBinary(bytes: Array[Byte]): CurrentShardState = {
|
|
|
|
|
val parsed = sm.CurrentShardState.parseFrom(bytes)
|
|
|
|
|
CurrentShardState(parsed.getShardId, parsed.getEntityIdsList.asScala.toSet)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def shardStateFromProto(parsed: ClusterShardingMessages.ShardState): ShardState = {
|
|
|
|
|
ShardState(parsed.getShardId, parsed.getEntityIdsList.asScala.toSet)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def shardStateFromBinary(bytes: Array[Byte]): ShardState = {
|
|
|
|
|
val parsed = sm.ShardState.parseFrom(bytes)
|
|
|
|
|
ShardState(parsed.getShardId, parsed.getEntityIdsList.asScala.toSet)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def currentShardRegionStateToProto(evt: CurrentShardRegionState): sm.CurrentShardRegionState = {
|
|
|
|
|
val shards = evt.shards.map(shardStateToProto).asJava
|
|
|
|
|
val failed = evt.failed.asJava
|
|
|
|
|
sm.CurrentShardRegionState.newBuilder().addAllShards(shards).addAllFailed(failed).build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def currentShardRegionStateFromBinary(bytes: Array[Byte]): CurrentShardRegionState = {
|
|
|
|
|
val parsed = sm.CurrentShardRegionState.parseFrom(bytes)
|
|
|
|
|
val state: Set[ShardState] = parsed.getShardsList.asScala.map(shardStateFromProto).toSet
|
|
|
|
|
val failed: Set[String] = parsed.getFailedList.asScala.toSet
|
|
|
|
|
CurrentShardRegionState(state, failed)
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-09 17:34:19 +02:00
|
|
|
def serializeAddress(address: Address): sm.Address =
|
|
|
|
|
address match {
|
|
|
|
|
case Address(protocol, systemName, Some(host), Some(port)) =>
|
|
|
|
|
sm.Address.newBuilder().setProtocol(protocol).setSystem(systemName).setHostname(host).setPort(port).build()
|
|
|
|
|
case _ => throw new IllegalArgumentException(s"Address [$address] could not be serialized: host or port missing.")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def deserializeAddress(address: sm.Address): Address =
|
|
|
|
|
Address(address.getProtocol, address.getSystem, address.getHostname, address.getPort)
|
|
|
|
|
|
2015-08-17 16:11:52 +02:00
|
|
|
private def resolveActorRef(path: String): ActorRef = {
|
|
|
|
|
system.provider.resolveActorRef(path)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def compress(msg: MessageLite): Array[Byte] = {
|
|
|
|
|
val bos = new ByteArrayOutputStream(BufferSize)
|
|
|
|
|
val zip = new GZIPOutputStream(bos)
|
2016-02-15 16:15:05 +01:00
|
|
|
try msg.writeTo(zip)
|
|
|
|
|
finally zip.close()
|
2015-08-17 16:11:52 +02:00
|
|
|
bos.toByteArray
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private def decompress(bytes: Array[Byte]): Array[Byte] = {
|
|
|
|
|
val in = new GZIPInputStream(new ByteArrayInputStream(bytes))
|
|
|
|
|
val out = new ByteArrayOutputStream()
|
|
|
|
|
val buffer = new Array[Byte](BufferSize)
|
|
|
|
|
|
|
|
|
|
@tailrec def readChunk(): Unit = in.read(buffer) match {
|
2019-02-09 15:25:39 +01:00
|
|
|
case -1 => ()
|
|
|
|
|
case n =>
|
2015-08-17 16:11:52 +02:00
|
|
|
out.write(buffer, 0, n)
|
|
|
|
|
readChunk()
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-15 16:15:05 +01:00
|
|
|
try readChunk()
|
|
|
|
|
finally in.close()
|
2015-08-17 16:11:52 +02:00
|
|
|
out.toByteArray
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|