Compose and RethinkDB 2.3's drivers

TL;DR: The latest RethinkDB drivers don't work with previous versions of RethinkDB. Take steps to "pin" your drivers to a compatible version.

RethinkDB recently released their latest excellent update to their database in the form of version 2.3, "Fantasia". There's quite a few improvements in the new version such as user account support, a fold command, integrated SSL encryption and an official Windows version. You can read about them on RethinkDB's blog. We're working on incorporating support for those changes and releasing an updated RethinkDB.

What also happened was that RethinkDB took the opportunity to update the way clients and servers communicate and that can lead to some problems for Node, Ruby, Python, Java and Go users. The issue here is about drivers. Using Node.js as an example of the issue, it'll present itself something like this in practice:

$ node index.js                                                                                                                                                                          
ERROR: Received an unsupported protocol version. This port is for RethinkDB queries. Does your client driver version not match the server?  
^

SyntaxError: Unexpected token E  
    at Object.parse (native)
    at TLSSocket.handshake_callback (/Users/dj/sandbox/noderethink/node_modules/rethinkdb/net.js:624:35)
    at emitOne (events.js:90:13)
    at TLSSocket.emit (events.js:182:7)
    at readableAddChunk (_stream_readable.js:153:18)
    at TLSSocket.Readable.push (_stream_readable.js:111:10)
    at TLSWrap.onread (net.js:529:20)

What's breaking?

RethinkDB drivers use a wire protocol which lets clients talk to the server. You can read about it in Writing RethinkDB Drivers. The protocol got up to version 0.4 for RethinkDB 2.0 to 2.2 but for 2.3 there was a major change; specifically an updated protocol 1.0 which would be able to detect previous protocols and fall back to them. RethinkDB 2.3.0 servers support this new protocol, and previous protocol versions. One of the advantages of the new 1.0 protocol it that it can be updated much more easily so that in future, when a protocol change is introduced, the clients and servers will know how to fall back to a version of the protocol they both speak.

The catch is that this once-in-a-development lifecycle change also creates a break in compatibility. While older drivers are be able talk to the new RethinkDB 2.3 server, the new 2.3 drivers only speak version 1.0 of the protocol which means that clients using the newest driver can't speak to previous versions of the server.

If this sounds like it shouldn't affect you, think again. Modern software development platforms use package managers to download the various components that applications need to run. They are npm for Node, gem for Ruby, pip for Python, Maven for Java and Go has it baked into its platform. It makes development much easier - to add the RethinkDB driver to a Node project all you have to do is run npm install rethinkdb --save and you are ready to go. Or not. By default, these package managers download the latest version of the package which is sensible.

With the release of RethinkDB 2.3 though, all those repositories have had their RethinkDB drivers updated so if you ask to install a driver without qualifying what version you want, you'll get the 2.3 version. Then, when you go to connect to a Compose RethinkDB installation you get the protocol incompatibility message:

ERROR: Received an unsupported protocol version. This port is for RethinkDB queries. Does your client driver version not match the server?  

Of course, package managers do allow you to set the version, or range of versions, you want to go with your package. When you find yourself in this situation, you need to uninstall the latest driver, find out what the most recent previous driver you can download is – it'll be version 2.2.something – and install that.

The Solutions...

Node.js

To install the correct driver to talk to Compose servers run:

npm uninstall rethinkdb  
npm install rethinkdb@2.2.3  

You can add a dependency in your package.json file so that it only uses a version prior to 2.3.0 like this:

{ "dependencies" :
  { "rethinkdb" : "<2.3.0" }
}

Ruby

For Ruby, the quick way to set up the driver is to run:

gem uninstall rethinkdb  
gem install rethinkdb -v 2.2.0.4  

You can get a list of available versions by running gem list -ra rethinkdb. You can specify in your applications Gemfile that you want any driver up to but not including 2.3.0 and later by adding:

gem 'rethinkdb', '< 2.3.0'  

Python

For Python applications, you need to run:

pip uninstall rethinkdb  
pip install rethinkdb==2.2.0.post6  

If you want an idea of what versions are available in future, run pip install rethinkdb==noversion and the pip will fail to find version "noversion" and list all the other available versions. If your Python program has a pip requirements file, add this to require a pre-2.3.0 driver:

rethinkdb >=2.2.0,<2.3.0  

There is, we are told, an undocumented flag in the 2.3.0 driver which lets it talk to older RethinkDB databases, designed mainly for testing. It's probably best to ignore that though as it will involve modifying your code to use an unsupported path and why do that when you can just set versions as part of the build.

Java

There's no world of command line package management for Java; it tends to be all declared in build configuration files for the various tools. With Maven, as an example, you may have this in your pom.xml:

  <dependency>
    <groupId>com.rethinkdb</groupId>
    <artifactId>rethinkdb-driver</artifactId>
    <version>LATEST</version>
  </dependency>
  ```

 This would pull the latest version of the driver down. It's not that common a setting – Java developers often set version numbers in their `pom.xml` files – but it is how you can unwittingly be caught by this protocol change. Simply replace the version tag with:

 ```
     <version>2.2-beta-6</version>

This, of course, pins the application to that version and we're done.

Go

The previous drivers are all official drivers, but our favourite unofficial driver is GoRethink. If you use v1 of the driver you won't need to do anything as that just supports the 0.4 protocol. If you upgrade – which means specifically importing the v2 package - then that does use the 1.0 protocol by default, but even there as the CHANGELOG notes, you can set the HandshakeVersion to 0.4 when connecting to enable access to older servers.