| --- |
| layout: post |
| title: "Cap'n Proto v0.4: Time Traveling RPC" |
| author: kentonv |
| --- |
| |
| Well, [Hofstadter](http://en.wikipedia.org/wiki/Hofstadter's_law) kicked in and this release took |
| way too long. But, after three long months, I'm happy to announce: |
| |
| ### Time-Traveling RPC _(Promise Pipelining)_ |
| |
| <img src='{{ site.baseurl }}images/time-travel.png' style='max-width:639px'> |
| |
| v0.4 finally introduces the long-promised [RPC system]({{ site.baseurl }}rpc.html). Traditionally, |
| RPC is plagued by the fact that networks have latency, and pretending that latency doesn't exist by |
| hiding it behind what looks like a normal function call only makes the problem worse. |
| Cap'n Proto has a simple solution to this problem: send call results _back in time_, so they |
| arrive at the client at the point in time when the call was originally made! |
| |
| Curious how Cap'n Proto bypasses the laws of physics? |
| [Check out the docs!]({{ site.baseurl }}rpc.html) |
| |
| _UPDATE: There has been some confusion about what I'm claiming. I am NOT saying that using |
| promises alone (i.e. being asynchronous) constitutes "time travel". Cap'n Proto implements a |
| technique called Promise Pipelining which allows a new request to be formed based on the content |
| of a previous result (in part or in whole) before that previous result is returned. Notice in the |
| diagram that the result of foo() is being passed to bar(). Please |
| [see the docs]({{ site.baseurl }}rpc.html) or |
| [check out the calculator example](https://github.com/kentonv/capnproto/blob/master/c++/samples) |
| for more._ |
| |
| ### Promises in C++ |
| |
| _UPDATE: More confusion. This section is **not** about pipelining ("time travel"). This section |
| is just talking about implementing a promise API in C++. Pipelining is another feature on top of |
| that. Please [see the RPC page]({{ site.baseurl }}rpc.html) if you want to know more about |
| pipelining._ |
| |
| If you do a lot of serious JavaScript programming, you've probably heard of |
| [Promises/A+](http://promisesaplus.com/) and similar proposals. Cap'n Proto RPC introduces a |
| similar construct in C++. In fact, the API is nearly identical, and its semantics are nearly |
| identical. Compare with |
| [Domenic Denicola's JavaScript example](http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/): |
| |
| {% highlight c++ %} |
| // C++ version of Domenic's JavaScript promises example. |
| getTweetsFor("domenic") // returns a promise |
| .then([](vector<Tweet> tweets) { |
| auto shortUrls = parseTweetsForUrls(tweets); |
| auto mostRecentShortUrl = shortUrls[0]; |
| // expandUrlUsingTwitterApi returns a promise |
| return expandUrlUsingTwitterApi(mostRecentShortUrl); |
| }) |
| .then(httpGet) // promise-returning function |
| .then( |
| [](string responseBody) { |
| cout << "Most recent link text:" << responseBody << endl; |
| }, |
| [](kj::Exception&& error) { |
| cerr << "Error with the twitterverse:" << error << endl; |
| } |
| ); |
| {% endhighlight %} |
| |
| This is C++, but it is no more lines -- nor otherwise more complex -- than the equivalent |
| JavaScript. We're doing several I/O operations, we're doing them asynchronously, and we don't |
| have a huge unreadable mess of callback functions. Promises are based on event loop concurrency, |
| which means you can perform concurrent operations with shared state without worrying about mutex |
| locking -- i.e., the JavaScript model. (Of course, if you really want threads, you can run |
| multiple event loops in multiple threads and make inter-thread RPC calls between them.) |
| |
| [More on C++ promises.]({{ site.baseurl }}cxxrpc.html#kj_concurrency_framework) |
| |
| ### Python too |
| |
| [Jason](https://github.com/jparyani) has been diligently keeping his |
| [Python bindings](http://jparyani.github.io/pycapnp/) up to date, so you can already use RPC there |
| as well. The Python interactive interpreter makes a great debugging tool for calling C++ servers. |
| |
| ### Up Next |
| |
| Cap'n Proto is far from done, but working on it in a bubble will not produce ideal results. |
| Starting after the holidays, I will be refocusing some of my time into an adjacent project which |
| will be a heavy user of Cap'n Proto. I hope this experience will help me discover first hand |
| the pain points in the current interface and keep development going in the right direction. |
| |
| This does, however, mean that core Cap'n Proto development will slow somewhat (unless contributors |
| pick up the slack! ;) ). I am extremely excited about this next project, though, and I think you |
| will be too. Stay tuned! |