Run Multiple FoundationDB Clusters on macOS

The FoundationDB documentation provides a guide to Getting Started on macOS. Follow that guide and install the base FoundationDB client and server libraries.

I currently develop in Ruby, so I also downloaded the official Ruby gem from the FoundationDB downloads page, and then ran gem install ~/Downloads/fdb-6.1.8.gem so that it was available locally to RubyGems.

With this setup it’s easy to connect Ruby to FoundationDB and develop on macOS. But what happens when you want to test your code? Running clear_range('', '\xFF') is a common test practice but will also clear your development data.

You could namespace your data, but that makes application configuration and achieving production parity more difficult. It’s often easier to instead run a dedicated FoundationDB test database.

Follow the link on Starting and stopping and note the location of the file provided to launchctl. Copy that file and modify the contents as follows.

cp /Library/LaunchDaemons/com.foundationdb.fdbmonitor.plist /Library/LaunchDaemons/com.foundationdb.fdbmonitor.test.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.foundationdb.fdbmonitor.test</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/libexec/fdbmonitor</string>
      <string>--conffile</string>
      <string>/usr/local/etc/foundationdb/foundationdb.test.conf</string>
      <string>--lockfile</string>
      <string>/var/run/FoundationDB.test.pid</string>
    </array>
    <key>KeepAlive</key>
    <true/>
  </dict>
</plist>

In addition to the name change, the two provided arguments now specify independent test versions of the configuration and lock files. (We could have used any name instead of “test”.)

Now copy the default configuration file to its new location and modify the contents as follows.

cp /usr/local/etc/foundationdb/foundationdb.conf /usr/local/etc/foundationdb/foundationdb.test.conf

[general]
restart_delay = 60
cluster_file = /usr/local/etc/foundationdb/fdb.test.cluster

[fdbserver]
command = /usr/local/libexec/fdbserver
public_address = auto:$ID
listen_address = public
datadir = /usr/local/foundationdb/data/$ID
logdir = /usr/local/foundationdb/logs

[fdbserver.4690]

Compared to the default configuration file, we’ve specified a test-specific cluster file and modified the port of the one server process to 4690. I also removed the backup agent configuration, as my test database is only active for the length of a test run.

Next, copy the default cluster file to its new location and modify the contents as follows.

cp /usr/local/etc/foundationdb/fdb.cluster /usr/local/etc/foundationdb/fdb.test.cluster

test:test@127.0.0.1:4690

You are now ready to start the second FoundationDB cluster. Run this command to do so:

sudo launchctl load -w /Library/LaunchDaemons/com.foundationdb.fdbmonitor.test.plist

Omit the -w flag if you do not want to start this cluster at boot.

To specify which FoundationDB cluster to access, simply pass the location of the cluster file into your client language’s open command:

require 'fdb'
FDB.api_version(600)
db = FDB.open(ENV['FDB_CLUSTER_FILE'])
db['foo'] = 'bar'

In a later article I’ll outline how to achive similar results using Docker and Docker Compose on macOS.