Adding support for non-delivery notifications on server-side as well + more code cleanup
This commit is contained in:
parent
7a0e8a82de
commit
00840c8f5a
2 changed files with 42 additions and 40 deletions
|
|
@ -99,6 +99,10 @@ case class RemoteServerClientDisconnected(
|
|||
case class RemoteServerClientClosed(
|
||||
@BeanProperty val server: RemoteServerModule,
|
||||
@BeanProperty val clientAddress: Option[InetSocketAddress]) extends RemoteServerLifeCycleEvent
|
||||
case class RemoteServerWriteFailed(
|
||||
@BeanProperty request: AnyRef,
|
||||
@BeanProperty cause: Throwable,
|
||||
@BeanProperty client: RemoteServerModule, remoteAddress: InetSocketAddress) extends RemoteServerLifeCycleEvent
|
||||
|
||||
/**
|
||||
* Thrown for example when trying to send a message using a RemoteClient that is either not started or shut down.
|
||||
|
|
|
|||
|
|
@ -511,7 +511,6 @@ class NettyRemoteSupport extends RemoteSupport with NettyRemoteServerModule with
|
|||
val home = this.address
|
||||
if (host == home.getHostName && port == home.getPort) {//TODO: switch to InetSocketAddress.equals?
|
||||
val localRef = findActorByIdOrUuid(serviceId,serviceId)
|
||||
|
||||
if (localRef ne null) return localRef //Code significantly simpler with the return statement
|
||||
}
|
||||
}
|
||||
|
|
@ -804,14 +803,29 @@ class RemoteServerHandler(
|
|||
val applicationLoader: Option[ClassLoader],
|
||||
val server: NettyRemoteServerModule) extends SimpleChannelUpstreamHandler with Logging {
|
||||
import RemoteServerSettings._
|
||||
|
||||
val AW_PROXY_PREFIX = "$$ProxiedByAW".intern
|
||||
val CHANNEL_INIT = "channel-init".intern
|
||||
|
||||
applicationLoader.foreach(MessageSerializer.setClassLoader(_)) //TODO: REVISIT: THIS FEELS A BIT DODGY
|
||||
|
||||
val sessionActors = new ChannelLocal[ConcurrentHashMap[String, ActorRef]]()
|
||||
val typedSessionActors = new ChannelLocal[ConcurrentHashMap[String, AnyRef]]()
|
||||
|
||||
applicationLoader.foreach(MessageSerializer.setClassLoader(_)) //TODO: REVISIT: THIS FEELS A BIT DODGY
|
||||
//Writes the specified message to the specified channel and propagates write errors to listeners
|
||||
private def write(channel: Channel, message: AnyRef): Unit =
|
||||
channel.write(message).addListener(
|
||||
new ChannelFutureListener {
|
||||
def operationComplete(future: ChannelFuture): Unit = {
|
||||
if (future.isCancelled) {
|
||||
//Not interesting at the moment
|
||||
} else if (!future.isSuccess) {
|
||||
val socketAddress = future.getChannel.getRemoteAddress match {
|
||||
case i: InetSocketAddress => i
|
||||
case _ => null
|
||||
}
|
||||
server.notifyListeners(RemoteServerWriteFailed(message, future.getCause, server, socketAddress))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* ChannelOpen overridden to store open channels for a clean postStop of a node.
|
||||
|
|
@ -842,26 +856,20 @@ class RemoteServerHandler(
|
|||
}
|
||||
|
||||
override def channelDisconnected(ctx: ChannelHandlerContext, event: ChannelStateEvent) = {
|
||||
import scala.collection.JavaConversions.asScalaIterable
|
||||
val clientAddress = getClientAddress(ctx)
|
||||
log.slf4j.debug("Remote client [{}] disconnected from [{}]", clientAddress, server.name)
|
||||
|
||||
// stop all session actors
|
||||
val channelActors = sessionActors.remove(event.getChannel)
|
||||
if (channelActors ne null) {
|
||||
val elems = channelActors.elements
|
||||
while (elems.hasMoreElements) {
|
||||
val actor = elems.nextElement
|
||||
for (map <- Option(sessionActors.remove(event.getChannel));
|
||||
actor <- asScalaIterable(map.values)) {
|
||||
try { actor.stop } catch { case e: Exception => log.slf4j.warn("Couldn't stop {}",actor,e) }
|
||||
}
|
||||
}
|
||||
|
||||
val channelTypedActors = typedSessionActors.remove(event.getChannel)
|
||||
if (channelTypedActors ne null) {
|
||||
val elems = channelTypedActors.elements
|
||||
while (elems.hasMoreElements) {
|
||||
val actor = elems.nextElement
|
||||
// stop all typed session actors
|
||||
for (map <- Option(typedSessionActors.remove(event.getChannel));
|
||||
actor <- asScalaIterable(map.values)) {
|
||||
try { TypedActor.stop(actor) } catch { case e: Exception => log.slf4j.warn("Couldn't stop {}",actor,e) }
|
||||
}
|
||||
}
|
||||
|
||||
server.notifyListeners(RemoteServerClientDisconnected(server, clientAddress))
|
||||
}
|
||||
|
|
@ -914,11 +922,9 @@ class RemoteServerHandler(
|
|||
log.slf4j.debug("Dispatching to remote actor [{}:{}]", actorInfo.getTarget, actorInfo.getUuid)
|
||||
|
||||
val actorRef =
|
||||
try {
|
||||
createActor(actorInfo, channel).start
|
||||
} catch {
|
||||
try { createActor(actorInfo, channel).start } catch {
|
||||
case e: SecurityException =>
|
||||
channel.write(createErrorReplyMessage(e, request, AkkaActorType.ScalaActor))
|
||||
write(channel, createErrorReplyMessage(e, request, AkkaActorType.ScalaActor))
|
||||
server.notifyListeners(RemoteServerError(e, server))
|
||||
return
|
||||
}
|
||||
|
|
@ -949,13 +955,7 @@ class RemoteServerHandler(
|
|||
|
||||
if (exception.isDefined) {
|
||||
log.slf4j.debug("Returning exception from actor invocation [{}]",exception.get.getClass)
|
||||
try {
|
||||
channel.write(createErrorReplyMessage(exception.get, request, AkkaActorType.ScalaActor))
|
||||
} catch {
|
||||
case e: Throwable =>
|
||||
log.slf4j.debug("An error occurred in sending the reply",e)
|
||||
server.notifyListeners(RemoteServerError(e, server))
|
||||
}
|
||||
write(channel, createErrorReplyMessage(exception.get, request, AkkaActorType.ScalaActor))
|
||||
}
|
||||
else if (result.isDefined) {
|
||||
log.slf4j.debug("Returning result from actor invocation [{}]",result.get)
|
||||
|
|
@ -975,11 +975,7 @@ class RemoteServerHandler(
|
|||
// FIXME lift in the supervisor uuid management into toh createRemoteMessageProtocolBuilder method
|
||||
if (request.hasSupervisorUuid) messageBuilder.setSupervisorUuid(request.getSupervisorUuid)
|
||||
|
||||
try {
|
||||
channel.write(messageBuilder.build)
|
||||
} catch {
|
||||
case e: Throwable => server.notifyListeners(RemoteServerError(e, server))
|
||||
}
|
||||
write(channel, messageBuilder.build)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
@ -1015,7 +1011,8 @@ class RemoteServerHandler(
|
|||
AkkaActorType.TypedActor,
|
||||
None)
|
||||
if (request.hasSupervisorUuid) messageBuilder.setSupervisorUuid(request.getSupervisorUuid)
|
||||
channel.write(messageBuilder.build)
|
||||
|
||||
write(channel, messageBuilder.build)
|
||||
log.slf4j.debug("Returning result from remote typed actor invocation [{}]", result)
|
||||
} catch {
|
||||
case e: Throwable => server.notifyListeners(RemoteServerError(e, server))
|
||||
|
|
@ -1024,7 +1021,8 @@ class RemoteServerHandler(
|
|||
messageReceiver.invoke(typedActor, args: _*) match {
|
||||
case f: Future[_] => //If it's a future, we can lift on that to defer the send to when the future is completed
|
||||
f.onComplete( future => {
|
||||
val result: Either[Any,Throwable] = if (future.exception.isDefined) Right(future.exception.get) else Left(future.result.get)
|
||||
val result: Either[Any,Throwable] =
|
||||
if (future.exception.isDefined) Right(future.exception.get) else Left(future.result.get)
|
||||
sendResponse(result)
|
||||
})
|
||||
case other => sendResponse(Left(other))
|
||||
|
|
@ -1032,10 +1030,10 @@ class RemoteServerHandler(
|
|||
}
|
||||
} catch {
|
||||
case e: InvocationTargetException =>
|
||||
channel.write(createErrorReplyMessage(e.getCause, request, AkkaActorType.TypedActor))
|
||||
write(channel, createErrorReplyMessage(e.getCause, request, AkkaActorType.TypedActor))
|
||||
server.notifyListeners(RemoteServerError(e, server))
|
||||
case e: Throwable =>
|
||||
channel.write(createErrorReplyMessage(e, request, AkkaActorType.TypedActor))
|
||||
write(channel, createErrorReplyMessage(e, request, AkkaActorType.TypedActor))
|
||||
server.notifyListeners(RemoteServerError(e, server))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue