Commit b06ff395 authored by Kenton Varda's avatar Kenton Varda

More doc updates, blog post.

parent 425657bb
safe: true
permalink: /news/:year-:month-:day-:title.html
baseurl: /capnproto/
is_next: false
safe: true
permalink: /news/:year-:month-:day-:title.html
baseurl: /capnproto/next/
is_next: true
......@@ -27,6 +27,15 @@
<a id="forkme_banner" href="https://github.com/kentonv/capnproto">View on GitHub</a>
</div>
{% if site.is_next %}
<div id="next_banner">
<h1>PREVIEW</h1>
<p>You are looking at the site as it will appear after the next release. This is a draft
version that may be incomplete, buggy, or not yet applicable. To look at the current
site, <a href="../">click here</a>.
</div>
{% endif %}
<!-- MAIN CONTENT -->
<div id="main_content_wrap" class="outer">
......
......@@ -17,7 +17,7 @@ href="https://groups.google.com/group/capnproto-announce">Stay Updated</a></div>
{{ content }}
<script type="text/javascript">setupNewsSidebar([
{% for post in site.posts %}
{ title: "{{ post.title }}", url: "/capnproto{{ post.url }}" },
{ title: "{{ post.title }}", url: "{{ site.baseurl }}.{{ post.url }}" },
{% endfor %}
]);</script>
{% include footer.html %}
---
layout: post
title: "Cap'n Proto v0.4: Time Traveling RPC"
author: kentonv
---
Well, Hofstadter kicked in and this release took way too long. But, after three long months, I'm
happy to announce...
### Time-Traveling RPC
<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 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)
### Promises in C++
If you do any 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 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.)
[More on C++ promises.]({{ site.baseurl }}cxxrpc.html#kj_concurrency_framework)
### 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 experience 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!
......@@ -75,7 +75,7 @@ kj::Promise<kj::String> contentPromise =
fetchHttp("http://example.com");
kj::Promise<int> lineCountPromise =
promise.then([](kj::String& content) {
promise.then([](kj::String&& content) {
return countChars(content, '\n');
});
{% endhighlight %}
......@@ -98,7 +98,7 @@ block.
{% highlight c++ %}
kj::Promise<int> lineCountPromise =
promise.then([](kj::String& content) {
promise.then([](kj::String&& content) {
return countChars(content, '\n');
}, [](kj::Exception&& exception) {
// Error! Pretend the document was empty.
......@@ -152,7 +152,7 @@ called when the promise either completes or is canceled.
### Other Features
KJ promise a number of primitive operations that can be performed on promises. The complete API
KJ supports a number of primitive operations that can be performed on promises. The complete API
is documented directly in the `kj/async.h` header. Additionally, see the `kj/async-io.h` header
for APIs for performing basic network I/O -- although Cap'n Proto RPC users typically won't need
to use these APIs directly.
......
......@@ -140,8 +140,7 @@ that value to mean "not present".
Pointer fields are a bit different. They start out "null", and you can check for nullness using
the `hasFoo()` accessor. You could use a null pointer to mean "not present". Note, though, that
calling `getFoo()` on a null pointer returns the default value, which is indistinguishable from a
legitimate value. The receiver of the message therefore needs to explicitly check `hasFoo()`
before calling the getter.
legitimate value, so checking `hasFoo()` is in fact the _only_ way to detect nullness.
### How do I resize a list?
......
function initSidebar() {
var filename = document.location.pathname.slice("/capnproto".length);
if (filename.slice(0, 5) == "/next") {
filename = filename.slice(5);
}
if (filename == "/") {
filename = "/index.html";
} else if (filename.slice(0, 6) == "/news/") {
......
......@@ -10,7 +10,7 @@ href="https://groups.google.com/group/capnproto-announce">Stay Updated</a></div>
<h1>News</h1>
{% for post in site.posts %}
<h2><a href="/capnproto{{ post.url }}">{{ post.title }}</a></h2>
<h2><a href="{{ site.baseurl }}.{{ post.url }}">{{ post.title }}</a></h2>
<p class="author">
<a href="https://github.com/{{ post.author }}">{{ post.author }}</a>
{% if post.author == 'kentonv' %}
......
#! /bin/bash
set -eu
shopt -s extglob
if [ "x$(git status --porcelain)" != "x" ]; then
echo "error: git repo has uncommited changes." >&2
exit 1
echo -n "git repo has uncommited changes. Continue anyway? (y/N) " >&2
read -n 1 YESNO
echo >&2
if [ "x$YESNO" != xy ]; then
exit 1
fi
fi
case $(git rev-parse --abbrev-ref HEAD) in
master )
echo "On master branch. Will generate to /next."
CONFIG=_config_next.yml
PREFIX=/next
LABEL="preview site"
;;
release-* )
echo "On release branch. Will generate to /."
CONFIG=_config.yml
PREFIX=
LABEL="site"
;;
* )
echo "Unrecognized branch." >&2
exit 1
;;
esac
echo "Checking out doc branch in ./.gh-pages..."
if [ ! -e .gh-pages ]; then
git clone -b gh-pages https://github.com/kentonv/capnproto.git .gh-pages
git clone -b gh-pages git@github.com:kentonv/capnproto.git .gh-pages
cd .gh-pages
else
cd .gh-pages
......@@ -26,16 +52,17 @@ cd ..
echo "Regenerating site..."
rm -rf _site .gh-pages/*
rm -rf _site .gh-pages$PREFIX/!(next)
jekyll build --safe
cp -r _site/* .gh-pages
jekyll build --safe --config $CONFIG
mkdir -p .gh-pages$PREFIX
cp -r _site/* .gh-pages$PREFIX
REV="$(git rev-parse HEAD)"
cd .gh-pages
git add *
git commit -m "site generated @$REV"
git commit -m "$LABEL generated @$REV"
if [ "x$(git status --porcelain)" != "x" ]; then
echo "error: .gh-pages is not clean after commit." >&2
......@@ -46,7 +73,7 @@ echo -n "Push now? (y/N)"
read -n 1 YESNO
echo
if [ "$YESNO" == "y" ]; then
if [ "x$YESNO" == "xy" ]; then
git push
cd ..
else
......
......@@ -45,8 +45,8 @@ OK, fair enough. In a traditional RPC system, we might solve our problem by int
method `foobar()` which combines `foo()` and `bar()`. Now we've eliminated the round trip, without
inventing a new protocol.
The problem is, this kind of arbitrary combining of orthogonal features quickly turns nice, elegant
object-oriented protocols into ad-hoc procedural messes.
The problem is, this kind of arbitrary combining of orthogonal features quickly turns elegant
object-oriented protocols into ad-hoc messes.
For example, consider the following interface:
......@@ -81,7 +81,7 @@ interface File {
}
{% endhighlight %}
This a very clean interface for interacting with a file system. But say you are using this
This is a very clean interface for interacting with a file system. But say you are using this
interface over a satellite link with 1000ms latency. Now you have a problem: simply reading the
file `foo` in directory `bar` takes four round trips!
......@@ -102,7 +102,7 @@ So now you're going to change it. You'll probably do something like:
call takes a path as an argument.
{% highlight capnp %}
# A sad, singleton-y interface.
# A sad, singleton-ish interface.
interface Filesystem {
list @0 (path :Text) -> (list :List(Text));
......@@ -176,10 +176,10 @@ for others to access the capability without consent of either the host or the re
the host only assigns it an ID specific to the connection over which it was sent.
Capability-based design patterns -- which largely boil down to object-oriented design patterns --
work great with Cap'n Proto. Such patterns tend to be much more agile than traditional ACL-based
security, making it easy to keep security tight and avoid confused-deputy attacks while minimizing
pain for legitimate users. That said, you can of course implement ACLs or any other pattern on top
of capabilities.
work great with Cap'n Proto. Such patterns tend to be much more adaptable than traditional
ACL-based security, making it easy to keep security tight and avoid confused-deputy attacks while
minimizing pain for legitimate users. That said, you can of course implement ACLs or any other
pattern on top of capabilities.
## Protocol Features
......
......@@ -380,6 +380,28 @@ body.normal #main_content.inner {
padding: 50px 10px 30px 10px;
}
#next_banner {
position: absolute;
left: 100px;
right: 100px;
top: 100px;
z-index: 100;
border: 2px solid black;
background-color: rgba(196, 196, 196, 0.8);
text-align: center;
color: black;
padding: 30px;
}
#next_banner h1 {
color: black;
font-size: 750%;
}
#next_banner p {
margin: 1em 100px;
}
#project_title {
margin: 0;
color: #fff;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment