Hot questions for Using Cap'n Proto in boost

Question:

I'm trying to implement in capnproto something like boost's connect function which blocks and retries until the server is up, or basic_socket::async_connect that lets me implement a callback with which to try connecting once more.

For example, running this code:

auto ioContext = kj::setupAsyncIo();
auto address = ioContext.provider->getNetwork()                                              
               .parseAddress("localhost:7500").wait(ioContext.waitScope);
auto connection = address->connect().wait(ioContext.waitScope);

Would obviously throw an exception if the server is down.

So my questions are:

  1. Is there a way to register a callback that will handle connection/failure to connect?
  2. Is there a built in mechanism in capnproto that already enables automatic reconnection?

Answer:

There isn't anything built-in for this, but you could implement it fairly easily like so:

kj::Promise<kj::AsyncIoStream> keepTryingConnect(kj::NetworkAddress& addr) {
  return addr.connect().catch_(
      [&addr](kj::Exception&& e) -> kj::Promise<kj::Own<kj::AsyncIoStream>> {
    if (e.getType() == kj::Exception::Type::DISCONNECTED) {
      // Try again.
      return keepTryingConnect(addr);
    } else {
      // Propagate error.
      return kj::mv(e);
    }
  });
}

Note that the DISCONNECTED exception type is a catch-all for any type of transient network error, and is explicitly intended for this kind of purpose.

As for reconnecting on disconnect: The system cannot do this automatically, because Cap'n Proto won't know whether it's safe to retry in-flight requests and won't know how to rebuild any capabilities that were present on the connection. What you need to do is find places in your application where it makes sense to catch the DISCONNECTED exception type and then retry, much like in the code above.