Replying to remote client via reply only? - akka

According to the akka actor documentation one can reply using self.channel ! Message so the code will work locally. I would like to do the same with remote actors.
I have:
class ServerActor extends Actor {
def receive = {
case "Hello" =>
self.channel ! "World"
}
}
and
class ClientActor extends Actor {
val remote = ...
def receive = {
case "Start" =>
remote ! "Hello"
case "World" =>
println("World received")
}
}
This works in so far as the ServerActor receives the "Hello" and sends a "World" message to a ClientActor. Unfortunately, it seems that the ClientActor receiving the message is one that is created in the servers VM, not the one that actually sent it (in the client VM).
Is there a way to make this work?
PS: It works when I do a self reply "World" and remote ? "Hello", however, I would rather send a message than replying.
EDIT: Thanks to everyone. Starting remoting on both ends was the problem. Others finding this question beware:
When using letting clients receive their responses in a non-blocking manner (as in not using remote ? request), shutting them down immediately on receiving a shutdown message, will cause some strange behavior (mentioned in my comments below); possibly by design due (to akka's let-it-fail fault-tolerance?). As clients are not waiting for a response shutting them down immediately on receiving a shutdown message will result in the following (on akka-1.2): Since the "original clients" no longer exist (but the round-trip "is still in progress") they are restarted --- strangely --- both on the client and the server.

I think it is the same problem I had. You need to start up a server instance on the client aswell when you want receive messages from the server.
The exception is when you're explicitly are asking for a result with question-mark operator.

Related

detect client connection closed in the grpc server

In the unary RPC example provided in the grpc Github (client) and (server), is there any way to detect client's closed connection?
For example, in server.cc file:
std::string prefix("Hello ");
reply_.set_message(prefix + request_.name());
// And we are done! Let the gRPC runtime know we've finished, using the
// memory address of this instance as the uniquely identifying tag for
// the event.
status_ = FINISH;
int p = 0,i=0;
while(i++ < 1000000000) { // some dummy work
p = p + 10;
}
responder_.Finish(reply_, Status::OK, this);
With this dummy task before sending the response back to the client, server will take a few seconds. If we close the client (for example say with Ctrl+C), the server does not throw any error. It simply calls Finish and then deallocates the object as if the Finish is successful.
Is there any async feature (handler function) on the server-side to get us notified that the client has closed the connection or client is terminated?
Thank You!
Unfortunately, no.
But now guys from gRPC team works hard to implement callback mechanism into C++ implementation. As I understand it will work the same way as on Java implementation( https://youtu.be/5tmPvSe7xXQ?t=1843 ).
You can see how to work with future API with next examples: client_callback.cc and server_callback.cc
And the point of your interest there is ServerBidiReactor class from ::grpc::experimental namespace for server side. It have OnDone and OnCancel notification methods that maybe can help you.
Another interesting point there is that you can store a pointers to connection object and send notifications to client at any time.
But it still have many issue and I don't recommend to use this API in production code.
Current progress of C++ callbacks implementation you can see there: https://github.com/grpc/grpc/projects/12#card-12554506

How to make sure last AMQP message is published successfully before closing connection?

I have multiple processes working together as a system. One of the processes acts as main process. When the system is shutting down, every process need to send a notification (via RabbitMQ) to the main process and then exit. The program is written in C++ and I am using AMQPCPP library.
The problem is that sometimes the notification is not published successfully. I suspect exiting too soon is the cause of the problem as AMQPCPP library has no chance to send the message out before closing its connection.
The documentation of AMQPCPP says:
Published messages are normally not confirmed by the server, and the RabbitMQ will not send a report back to inform you whether the message was succesfully published or not. Therefore the publish method does not return a Deferred object.
As long as no error is reported via the Channel::onError() method, you can safely assume that your messages were delivered.
This can of course be a problem when you are publishing many messages. If you get an error halfway through there is no way to know for sure how many messages made it to the broker and how many should be republished. If this is important, you can wrap the publish commands inside a transaction. In this case, if an error occurs, the transaction is automatically rolled back by RabbitMQ and none of the messages are actually published.
Without a confirmation from RabbitMQ server, it's hard to decide when it is safe to exit the process. Furthermore, using transaction sounds like overkill for a notification.
Could anyone suggest a simple solution for a graceful shutting down without losing the last notification?
It turns out that I can setup a callback when closing the channel. So that I can safely close connection when all channels are closed successfully. I am not entirely sure if this process ensures all outgoing messages are really published. However from the test result, it seems that the problem is solved.
class MyClass
{
...
AMQP::TcpConnection m_tcpConnection;
AMQP::TcpChannel m_channelA;
AMQP::TcpChannel m_channelB;
...
};
void MyClass::stop(void)
{
sendTerminateNotification();
int remainChannel = 2;
auto closeConnection = [&]() {
--remainChannel;
if (remainChannel == 0) {
// close connection when all channels are closed.
m_tcpConnection.close();
ev::get_default_loop().break_loop();
}
};
auto closeChannel = [&](AMQP::TcpChannel & channel) {
channel.close()
.onSuccess([&](void) { closeConnection(); })
.onError([&](const char * msg)
{
std::cout << "cannot close channel: "
<< msg << std::endl;
// close the connection anyway
closeConnection();
}
);
closeChannel(m_channelA);
closeChannel(m_channelB);
}

How does akka know which specific message reply is associated with the correct future?

Lets say I ask (?) the same actor for two responses.
It stores the sender for later.
Later, it gets messages back to go to the senders. We get the right sender (the one hashed to the message) but how does Akka know which message the response is for?
Is there something in the ActorRef that indicates which message each response is for?
Is it the 'channel'?
I'd like to understand the underlying technology better.
I'll try to read the source at the same time but I think this is a really good question.
Code example:
class TestActor
[...]
def onReceive = {
case r: MessageToGoOut ⇒
messageId += 1
val requestId = clientConnectionId + messageId
senders += (requestId -> sender) //store sender for later
anotherActor ! WrappedUpMessage(requestId, MessageOut))
case m: MessageToGoBackToSender ⇒
val requestId = m.requestId
senders.get(requestId) map { client ⇒
client ! Response(m.message)
senders -= requestId
}
}
val futures = for(i <- 1 to 100) yield testActor ? new MessageToGoOut ("HEYO!" + i)
Now how does akka ensure the messages get back to the right actor??
Every Actor has a path. From inside of the Actor, you could say:
context.path
From outside an Actor, if you had an ActorRef, you could just say:
ref.path
This path if the address of that individual actor instance, and it's how I believe the internal routing system routes messages to the mailboxes for actors instances. When you are outside of an Actor, like you are when you are looping and sending messages in your example, when you use ask (the ?), a temporary Actor instance is started up so that when the Actor that received the message needs to response, it has a path to respond to. This is probably a bit of an oversimplification, and it might not be the level of detail that you are looking for, so I apologize if I missed the gist of your question.
Also, the sender var in an Actor is an ActorRef, thus it has a path so you can route back to it.
When a Future is created, akka creates a temporary (and addressable) Actor that is basically servicing that Future. When that temporary Actor sends to another Actor, its ActorRef is transmitted as the sender. When the receiving actor is processing that specific message, the sender var is set to the ActorRef for that temp actor, meaning that you have an address to respond to. Even if you decide to hold on to that sender for later, you still have an address to send back to and eventually complete the Future that the temporary actor is servicing. The point is, as long as you have an ActorRef, whether it's a request or a response, all it's doing is routing a message to the path for that ActorRef.
Ask (?) and tell (!) really aren't much different. Ask is basically a tell where the sender is expecting the receiver to tell a message back to it.

How to detect dead remote client or server in akka2

Im new to AKKA2.The following is my question:
There is a server actor and several client actors.
The server stores all the ref of the client actors.
I wonder how the server can detect which client is disconnected(shutdown, crash...)
And if there is a way to tell the clients that the server is dead.
There are two ways to interact with an actor's lifecycle. First, the parent of an actor defines a supervisory policy that handles actor failures and has the option to restart, stop, resume, or escalate after a failure. In addition, a non-supervisor actor can "watch" an actor to detect the Terminated message generated when the actor dies. This section of the docs covers the topic: http://doc.akka.io/docs/akka/2.0.1/general/supervision.html
Here's an example of using watch from a spec. I start an actor, then set up a watcher for the Termination. When the actor gets a PoisonPill message, the event is detected by the watcher:
"be able to watch the proxy actor fail" in {
val myProxy = system.actorOf(Props(new VcdRouterActor(vcdPrivateApiUrl, vcdUser, vcdPass, true, sessionTimeout)), "vcd-router-" + newUuid)
watch(myProxy)
myProxy ! PoisonPill
expectMsg(Terminated(`myProxy`))
}
Here's an example of a custom supervisor strategy that Stops the child actor if it failed due to an authentication exception since that probably will not be correctable, or escalates the failure to a higher supervisor if the failure was for another reason:
override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 5, withinTimeRange = 1 minutes) {
// presumably we had a connection, and lost it. Let's restart the child and see if we can re-establish one.
case e: AuthenticationException ⇒
log.error(e.message + " Stopping proxy router for this host")
Stop
// don't know what it was, escalate it.
case e: Exception ⇒
log.warning("Unknown exception from vCD proxy. Escalating a {}", e.getClass.getName)
Escalate
}
Within an actor, you can generate the failure by throwing an exception or handling a PoisonPill message.
Another pattern that may be useful if you don't want to generate a failure is to respond with a failure to the sender. Then you can have a more personal message exchange with the caller. For example, the caller can use the ask pattern and use an onComplete block for handling the response. Caller side:
vcdRouter ? DisableOrg(id) mapTo manifest[VcdHttpResponse] onComplete {
case Left(failure) => log.info("receive a failure message")
case Right(success) ⇒ log.info("org disabled)
}
Callee side:
val org0 = new UUID("00000000-0000-0000-0000-000000000000")
def receive = {
case DisableOrg(id: UUID) if id == org0 => sender ! Failure(new IllegalArgumentException("can't disable org 0")
case DisableOrg(id: UUID) => sender ! disableOrg(id)
}
In order to make your server react to changes of remote client status you could use something like the following (example is for Akka 2.1.4).
In Java
#Override
public void preStart() {
context().system().eventStream().subscribe(getSelf(), RemoteLifeCycleEvent.class);
}
Or in Scala
override def preStart = {
context.system.eventStream.subscribe(listener, classOf[RemoteLifeCycleEvent])
}
If you're only interested when the client is disconnected you could register only for RemoteClientDisconnected
More info here(java)and here(scala)
In the upcoming Akka 2.2 release (RC1 was released yesterday), Death Watch works both locally and remote. If you watch the root guardian on the other system, when you get Terminated for him, you know that the remote system is down.
Hope that helps!

How to display remote email message?

I have been using this code to display IMAP4 messages:
void DisplayMessageL( const TMsvId &aId )
{
// 1. construct the client MTM
TMsvEntry indexEntry;
TMsvId serviceId;
User::LeaveIfError( iMsvSession->GetEntry(aId, serviceId, indexEntry));
CBaseMtm* mtm = iClientReg->NewMtmL(indexEntry.iMtm);
CleanupStack::PushL(mtm);
// 2. construct the user interface MTM
CBaseMtmUi* uiMtm = iUiReg->NewMtmUiL(*mtm);
CleanupStack::PushL(uiMtm);
// 3. display the message
uiMtm->BaseMtm().SwitchCurrentEntryL(indexEntry.Id());
CMsvOperationWait* waiter=CMsvOperationWait::NewLC();
waiter->Start(); //we use synchronous waiter
CMsvOperation* op = uiMtm->OpenL(waiter->iStatus);
CleanupStack::PushL(op);
CActiveScheduler::Start();
// 4. cleanup for example even members
CleanupStack::PopAndDestroy(4); // op,waiter, mtm, uimtm
}
However, in case when user attempts to download a remote message (i.e. one of the emails previously not retrieved from the mail server), and then cancels the request, my code remains blocked, and it never receives information that the action was canceled.
My question is:
what is the workaround for the above, so the application is not stuck?
can anyone provide a working example for asynchronous call for opening remote messages which do not panic and crash the application?
Asynchronous calls for POP3, SMTP and local IMAP4 messages work perfectly, but remote IMAP4 messages create this issue.
I am testing these examples for S60 5th edition.
Thank you all in advance.
First of all, I would retry removing CMsvOperationWait and deal with the open request asynchronously - i.e. have an active object waiting for the CMsvOperation to complete.
CMsvOperationWait is nothing more than a convenience to make an asynch operation appear synchronous and my suspicion is that this is culprit - in the case of download->show message, there are two asynch operations chained.