コンパイラかく語りき

import { Fun } from 'programming'

rethinkdbdashを試してみる

RethinkDBのNodeドライバと言えば、公式のドライバがあります。もちろんこれは不満なく使うことができるのですが、どうやらrethinkdbdashという別のドライバもあるようです。

この記事ではrethinkdbdashの特徴や機能について、READMEを訳す形でメモしていきます。

存在意義

rethinkdbdashは、promisesとconnection poolを実験的に使用するために作られました。promiseは公式のドライバにも採用され、スタンスとしては公式ドライバの強化であるようです。

公式ドライバとの違い

1. モジュールロード時に実行する必要がある

// official
const r = require('rethinkdb') 

// rethinkdbdash
const r_not_called = require('rethinkdbdash') // Not enough... [Function: main]
const r_called     = require('rethinkdbdash')() // OK!

2. connectメソッドを呼ぶ必要が無い

ロード時の実行の際、自動的にconnectが行われます。便利ですね。

const r = require('rethinkdbdash')() 
// Creating a pool connected to localhost:28015

3. cursorがArrayになっている

const r = require('rethinkdbdash')()

r.table('user').run().then((result) => {
    console.log(Array.isArray(result)) // true
})

公式ドライバからの移行

完全対応する場合

// これを
var r = require('rethinkdb')

// こうする
var r = require('rethinkdbdash')({
    pool: false,
    cursor: true
})

rethinkdbdashの機能を活かしたい場合

// まずロードを書き換え
var r = require('rethinkdb') // 旧
var r = require('rethinkdbdash')() // 新

// コネクションに関する記述を削除
r.connect({host: ..., port: ...}).then(function(connection) {
    connection.on('error', handleError);
    query.run(connection).then(function(result) {
        // console.log(result);
        connection.close()
    });
}) // 旧

query.run().then(function(result) {
    // console.log(result);
}) // 新

// カーソルに関する記述を削除
r.table('data').run(connection).then(function(cursor) {
    cursor.toArray().then(function(result) {
        // console.log(result):
    })
}) // 旧

r.table('data').run().then(function(result) {
    // console.log(result);
}) // 新

TLSコネクション

RethinkDBはTLSコネクションをサポートしていませんが、以下の手順で実現できます。(※この機能はエクスペリメンタルです)

まず、サーバにTLSプロキシを立てます。

var tls = require('tls');
var net = require('net');
var tlsOpts = {
    key: '', // プライベートキー
    cert: '' // 公式証明書
};
tls.createServer(tlsOpts, function (encryptedConnection) {
    var rethinkdbConn = net.connect({
        host: 'localhost',
        port: 28015
    });
    encryptedConnection.pipe(rethinkdbConn).pipe(encryptedConnection);
}).listen(29015);

それから、安全な接続を行います。

var r = require('rethinkdbdash')({
  port: 29015,
  host: 'place-with-no-firewall.com',
  ssl: true
});

新機能

ドライバインポート

ドライバのインポート時に、以下のオプションを渡すことができます。

  • db: \ - 指定がない場合はデフォルトDBが使われます。
  • user: \ - RethinkDBユーザー。デフォルトはAdmin。
  • password: \ - ユーザーのパスワード。デフォルトは空文字。
  • discovery: \ - デフォルトではfalse。trueならば、定期的にserver_statusテーブルからデータをプルしてホスト一覧を最近に保ってくれる。
  • pool: \ - falseにするとコネクションプールを使わない。
  • buffer: \ - プールで利用可能なコネクションの最小数。デフォルトは50。
  • max: \ - プールで利用可能なコネクションの最大数。デフォルトは100。
  • timeout: \ - コネクションが開かれる時間を指定。デフォルトは20。
  • pingInterval: - もし0以上が指定されたら、コネクションはpingInterval秒ごとにpingされる。デフォルトは-1。
  • timeoutError: \ - エラー時の再接続間隔時間。デフォルトは1000。
  • timeoutGb: \ - 不使用のコネクションをどのくらい保持しておくか。デフォルトは60601000
  • silent: \ - console.error errors。デフォルトはfalse。
  • servers: {host: \, port: \}のArray - 接続するRethinkDBノード。
  • optionalRun: \ - falseにすると結果を残さないクエリ実行。デフォルトはtrue。

シングルインスタンスの場合、hostportを直接渡すことも可能。

// localhost:8080に接続し、他のインスタンスも発見できるようにさせる。
var r = require('rethinkdbdash')({
    discovery: true
});

// localhost:8080にだけ接続する。
var r = require('rethinkdbdash')();

// コネクションプールを作成しない。
var r = require('rethinkdbdash')({pool: false});

// `192.168.0.100`, `192.168.0.101`, `192.168.0.102`から送られてくるクラスタに接続する。
var r = require('rethinkdbdash')({
    servers: [
        {host: '192.168.0.100', port: 28015},
        {host: '192.168.0.101', port: 28015},
        {host: '192.168.0.102', port: 28015},
    ]
});

// `192.168.0.100`, `192.168.0.100`, `192.168.0.102` を含むクラスタに接続しつつ、最大接続数を3000に引き上げ300の接続を利用可能にする。
var r = require('rethinkdbdash')({
    servers: [
        {host: '192.168.0.100', port: 28015},
        {host: '192.168.0.101', port: 28015},
        {host: '192.168.0.102', port: 28015},
    ],
    buffer: 300,
    max: 3000
});

コネクションプール

クエリ発行後にNodeのscriptを閉じたい場合には、プールをdrainする必要がある。

r.getPoolMaster().drain();
var r = require('rethinkdbdash')();

const userTable = r.table('user').run()

r.getPoolMaster().drain()

userTable.then((res) => {
    console.log(res)
})
// Unhandled rejection ReqlDriverError: None of the pools have an opened connection and failed to open a new one.

また、プールマスターはerrorやnewステートをstderr上でロギングする。 logイベントに対してリスナをバインドすることで、ログを扱うことができる。

r.getPoolMaster().on('log', console.log);

その他、プールマスターを通じて実行できるメソッド。

var r = require('rethinkdbdash')();

const userTable = r.table('user').run()
const pointTable = r.table('point').run()

// オープンなコネクションの数。
console.log(r.getPoolMaster().getLength()) // 2

// アイドルなコネクションの数。クエリ実行中でないもの。
console.log(r.getPoolMaster().getAvailableLength()) // 0

// すべてのプールにアクセスできる。
console.log(r.getPoolMaster().getPools())

ストリーム

(TODO: 時間切れのため、あとで追記します。)