Remove access of state from spawnAdapter in ClustserReceptionist (#24336)
This commit is contained in:
parent
1d5b913f7f
commit
574e690330
2 changed files with 34 additions and 24 deletions
|
|
@ -36,13 +36,18 @@ private[akka] object ReceptionistImpl extends ReceptionistBehaviorProvider {
|
||||||
/**
|
/**
|
||||||
* Interface to allow plugging of external service discovery infrastructure in to the existing receptionist API.
|
* Interface to allow plugging of external service discovery infrastructure in to the existing receptionist API.
|
||||||
*/
|
*/
|
||||||
trait ExternalInterface {
|
trait ExternalInterface[State] {
|
||||||
def onRegister[T](key: ServiceKey[T], address: ActorRef[T]): Unit
|
def onRegister[T](key: ServiceKey[T], address: ActorRef[T]): Unit
|
||||||
def onUnregister[T](key: ServiceKey[T], address: ActorRef[T]): Unit
|
def onUnregister[T](key: ServiceKey[T], address: ActorRef[T]): Unit
|
||||||
|
def onExternalUpdate(update: State)
|
||||||
|
|
||||||
|
final case class RegistrationsChangedExternally(changes: Map[AbstractServiceKey, Set[ActorRef[_]]], state: State) extends ReceptionistInternalCommand
|
||||||
}
|
}
|
||||||
object LocalExternalInterface extends ExternalInterface {
|
|
||||||
|
object LocalExternalInterface extends ExternalInterface[LocalServiceRegistry] {
|
||||||
def onRegister[T](key: ServiceKey[T], address: ActorRef[T]): Unit = ()
|
def onRegister[T](key: ServiceKey[T], address: ActorRef[T]): Unit = ()
|
||||||
def onUnregister[T](key: ServiceKey[T], address: ActorRef[T]): Unit = ()
|
def onUnregister[T](key: ServiceKey[T], address: ActorRef[T]): Unit = ()
|
||||||
|
def onExternalUpdate(update: LocalServiceRegistry): Unit = ()
|
||||||
}
|
}
|
||||||
|
|
||||||
override def behavior: Behavior[Command] = localOnlyBehavior
|
override def behavior: Behavior[Command] = localOnlyBehavior
|
||||||
|
|
@ -57,12 +62,11 @@ private[akka] object ReceptionistImpl extends ReceptionistBehaviorProvider {
|
||||||
sealed abstract class ReceptionistInternalCommand extends InternalCommand
|
sealed abstract class ReceptionistInternalCommand extends InternalCommand
|
||||||
final case class RegisteredActorTerminated[T](key: ServiceKey[T], address: ActorRef[T]) extends ReceptionistInternalCommand
|
final case class RegisteredActorTerminated[T](key: ServiceKey[T], address: ActorRef[T]) extends ReceptionistInternalCommand
|
||||||
final case class SubscriberTerminated[T](key: ServiceKey[T], address: ActorRef[Listing[T]]) extends ReceptionistInternalCommand
|
final case class SubscriberTerminated[T](key: ServiceKey[T], address: ActorRef[Listing[T]]) extends ReceptionistInternalCommand
|
||||||
final case class RegistrationsChangedExternally(changes: Map[AbstractServiceKey, Set[ActorRef[_]]]) extends ReceptionistInternalCommand
|
|
||||||
|
|
||||||
type SubscriptionsKV[K <: AbstractServiceKey] = ActorRef[Listing[K#Protocol]]
|
type SubscriptionsKV[K <: AbstractServiceKey] = ActorRef[Listing[K#Protocol]]
|
||||||
type SubscriptionRegistry = TypedMultiMap[AbstractServiceKey, SubscriptionsKV]
|
type SubscriptionRegistry = TypedMultiMap[AbstractServiceKey, SubscriptionsKV]
|
||||||
|
|
||||||
private[akka] def init(externalInterfaceFactory: ActorContext[AllCommands] ⇒ ExternalInterface): Behavior[Command] =
|
private[akka] def init[State](externalInterfaceFactory: ActorContext[AllCommands] ⇒ ExternalInterface[State]): Behavior[Command] =
|
||||||
Behaviors.deferred[AllCommands] { ctx ⇒
|
Behaviors.deferred[AllCommands] { ctx ⇒
|
||||||
val externalInterface = externalInterfaceFactory(ctx)
|
val externalInterface = externalInterfaceFactory(ctx)
|
||||||
behavior(
|
behavior(
|
||||||
|
|
@ -71,10 +75,10 @@ private[akka] object ReceptionistImpl extends ReceptionistBehaviorProvider {
|
||||||
externalInterface)
|
externalInterface)
|
||||||
}.narrow[Command]
|
}.narrow[Command]
|
||||||
|
|
||||||
private def behavior(
|
private def behavior[State](
|
||||||
serviceRegistry: LocalServiceRegistry,
|
serviceRegistry: LocalServiceRegistry,
|
||||||
subscriptions: SubscriptionRegistry,
|
subscriptions: SubscriptionRegistry,
|
||||||
externalInterface: ExternalInterface): Behavior[AllCommands] = {
|
externalInterface: ExternalInterface[State]): Behavior[AllCommands] = {
|
||||||
|
|
||||||
// Helper to create new state
|
// Helper to create new state
|
||||||
def next(newRegistry: LocalServiceRegistry = serviceRegistry, newSubscriptions: SubscriptionRegistry = subscriptions) =
|
def next(newRegistry: LocalServiceRegistry = serviceRegistry, newSubscriptions: SubscriptionRegistry = subscriptions) =
|
||||||
|
|
@ -126,7 +130,7 @@ private[akka] object ReceptionistImpl extends ReceptionistBehaviorProvider {
|
||||||
|
|
||||||
same
|
same
|
||||||
|
|
||||||
case RegistrationsChangedExternally(changes) ⇒
|
case externalInterface.RegistrationsChangedExternally(changes, state) ⇒
|
||||||
|
|
||||||
ctx.system.log.debug("[{}] Registration changed: {}", ctx.self, changes)
|
ctx.system.log.debug("[{}] Registration changed: {}", ctx.self, changes)
|
||||||
|
|
||||||
|
|
@ -136,7 +140,7 @@ private[akka] object ReceptionistImpl extends ReceptionistBehaviorProvider {
|
||||||
case (reg, (key, values)) ⇒
|
case (reg, (key, values)) ⇒
|
||||||
reg.setAll(key)(values.asInstanceOf[Set[ActorRef[key.Protocol]]])
|
reg.setAll(key)(values.asInstanceOf[Set[ActorRef[key.Protocol]]])
|
||||||
}
|
}
|
||||||
|
externalInterface.onExternalUpdate(state)
|
||||||
updateRegistry(changes.keySet, makeChanges) // overwrite all changed keys
|
updateRegistry(changes.keySet, makeChanges) // overwrite all changed keys
|
||||||
|
|
||||||
case RegisteredActorTerminated(key, serviceInstance) ⇒
|
case RegisteredActorTerminated(key, serviceInstance) ⇒
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ private[typed] object ClusterReceptionist extends ReceptionistBehaviorProvider {
|
||||||
/**
|
/**
|
||||||
* Returns an ReceptionistImpl.ExternalInterface that synchronizes registered services with
|
* Returns an ReceptionistImpl.ExternalInterface that synchronizes registered services with
|
||||||
*/
|
*/
|
||||||
def clusteredReceptionist(settings: ClusterReceptionistSettings = ClusterReceptionistSettings())(ctx: ActorContext[AllCommands]): ReceptionistImpl.ExternalInterface = {
|
def clusteredReceptionist(settings: ClusterReceptionistSettings = ClusterReceptionistSettings())(ctx: ActorContext[AllCommands]): ReceptionistImpl.ExternalInterface[ServiceRegistry] = {
|
||||||
import akka.actor.typed.scaladsl.adapter._
|
import akka.actor.typed.scaladsl.adapter._
|
||||||
val untypedSystem = ctx.system.toUntyped
|
val untypedSystem = ctx.system.toUntyped
|
||||||
|
|
||||||
|
|
@ -87,21 +87,7 @@ private[typed] object ClusterReceptionist extends ReceptionistBehaviorProvider {
|
||||||
.foldLeft(Map.empty[AbstractServiceKey, Set[ActorRef[_]]])(changesForKey(_, _))
|
.foldLeft(Map.empty[AbstractServiceKey, Set[ActorRef[_]]])(changesForKey(_, _))
|
||||||
}
|
}
|
||||||
|
|
||||||
val adapter: ActorRef[Replicator.ReplicatorMessage] =
|
val externalInterface = new ExternalInterface[ServiceRegistry] {
|
||||||
ctx.spawnAdapter[Replicator.ReplicatorMessage] { (x: Replicator.ReplicatorMessage) ⇒
|
|
||||||
x match {
|
|
||||||
case changed @ Replicator.Changed(ReceptionistKey) ⇒
|
|
||||||
val value = changed.get(ReceptionistKey)
|
|
||||||
val oldState = state
|
|
||||||
state = ServiceRegistry(value) // is that thread-safe?
|
|
||||||
val changes = diff(oldState, state)
|
|
||||||
RegistrationsChangedExternally(changes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
replicator ! Replicator.Subscribe(ReceptionistKey, adapter.toUntyped)
|
|
||||||
|
|
||||||
new ExternalInterface {
|
|
||||||
private def updateRegistry(update: ServiceRegistry ⇒ ServiceRegistry): Unit = {
|
private def updateRegistry(update: ServiceRegistry ⇒ ServiceRegistry): Unit = {
|
||||||
state = update(state)
|
state = update(state)
|
||||||
replicator ! Replicator.Update(ReceptionistKey, EmptyORMultiMap, settings.writeConsistency) { registry ⇒
|
replicator ! Replicator.Update(ReceptionistKey, EmptyORMultiMap, settings.writeConsistency) { registry ⇒
|
||||||
|
|
@ -114,6 +100,26 @@ private[typed] object ClusterReceptionist extends ReceptionistBehaviorProvider {
|
||||||
|
|
||||||
def onUnregister[T](key: ServiceKey[T], address: ActorRef[T]): Unit =
|
def onUnregister[T](key: ServiceKey[T], address: ActorRef[T]): Unit =
|
||||||
updateRegistry(_.removeBinding(key, address))
|
updateRegistry(_.removeBinding(key, address))
|
||||||
|
|
||||||
|
def onExternalUpdate(update: ServiceRegistry): Unit = {
|
||||||
|
state = update
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val adapter: ActorRef[Replicator.ReplicatorMessage] =
|
||||||
|
ctx.spawnAdapter[Replicator.ReplicatorMessage] { (x: Replicator.ReplicatorMessage) ⇒
|
||||||
|
x match {
|
||||||
|
case changed @ Replicator.Changed(ReceptionistKey) ⇒
|
||||||
|
val value = changed.get(ReceptionistKey)
|
||||||
|
val oldState = state
|
||||||
|
val newState = ServiceRegistry(value)
|
||||||
|
val changes = diff(oldState, newState)
|
||||||
|
externalInterface.RegistrationsChangedExternally(changes, newState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
replicator ! Replicator.Subscribe(ReceptionistKey, adapter.toUntyped)
|
||||||
|
|
||||||
|
externalInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue