Inspirel banner

YAMI4 Tip #5 - Let Me Think

YAMI4 supports asynchronous messaging and we have already covered what it means from the client's perspective. In essence, the client does not have to block waiting for the message to be processed and instead can continue doing other tasks - this is a very useful property in GUI applications or when dealing with large number of messages at the same time.

But YAMI4 is also asynchronous on the server side, even though this is not immediately obvious from the fact that a callback invocation is used to deliver the message.

The callback interface in Java looks like this:

public interface IncomingMessageCallback {

    void call(IncomingMessage message) throws Exception;

}

This concept is similar in other supported programming languages, but can rely on other idioms - for example, in C++ the callback can be delivered to any callable entity, including functors with overloaded function call operators - but on the fundamental level it is always the same: the incoming message is delievered to the server program and the server is supposed to do something with the message.

In particular the calculator example shows that the server can immediately prepare the response and therefore the whole message can be processed within the single callback invocation:

    private static class Calculator
        implements IncomingMessageCallback {

        @Override
        public void call(IncomingMessage im)
            throws Exception {

            // get the parameters, compute the result and prepare it
            // ...

            im.reply(replyParams);
        }
    }
}

Above, the whole processing of the incoming message happens within a single callback invocation, which makes it a synchronous operation.

But what if the message cannot be processed immediately, and instead the server needs a bit of time to prepare the response?

The easiest way to do it is to just do the lenghty part of processing directly within the callback, but the price for this is that the dispatcher thread that is executing the callback invocation will be blocked and will not be able to process other incoming messages during that time. This can be forgiven in the most simple servers, but might not be acceptable in the real-life production systems.

The solution is to put the incoming message object aside and just return from the callback without replying. There is no need to prepare the response immediately within the callback - in other words, even though the callback has the interface that suggests synchronous processsing, it is the incoming message object that is in focus here and its reply() method can be executed at any time - in particular later. If the server needs some time to work on the response, the most natural way to do it is to put the incoming message object aside, perhaps in some collection, and let other dedicated server threads work on it at their own pace. Once the response is ready, the reply() method can be called on the incoming message object, which will then delegate it to the managing agent for transmission back to the client. The only limitation is that the reply() method can be called at most once, but there is no practical limit on when it should happen or from which thread it should be done.

Thanks to this asynchronous approach the server can deal with long requests or with bursts of requests that could not be handled immediately, all without blocking internal agent threads.

Previous tip: Truly Non-Blocking Send

Next tip: Taking Care Of UDP