Git Product home page Git Product logo

rethinkdbdash's Introduction

rethinkdbdash

Wercker status

A Node.js driver for RethinkDB with more advanced features.

Install

npm install rethinkdbdash

Note: The rethinkdbdash-unstable package is a relic from the past (rethinkdb < 1.13).

Quick start

Rethinkdbdash uses almost the same API as the official driver. Please refer to the official driver's documentation for all the ReQL methods (the methods used to build the query).

The main differences are:

  • You need to execute the module when you import it:
var r = require('rethinkdbdash')();
// With the official driver:
// var r = require('rethinkdb');
  • Connections are managed by the driver with an efficient connection pool. Once you have imported the driver, you can immediately run queries, you don't need to call r.connect, or pass a connection to run.
var r = require('rethinkdbdash')();
r.table('users').get('[email protected]').run().then(function(user) {
  // ...
}).error(handleError)
  • Cursors are coerced to arrays by default
var r = require('rethinkdbdash')();
r.table('data').run().then(function(result) {
  assert(Array.isArray(result)) // true
  // With the official driver you need to call
  // result.toArray().then(function(result2) {
  //   assert(Array.isArray(result2))
  // })
});

Drop in

You can replace the official driver with rethinkdbdash by just replacing

var r = require('rethinkdb');

With:

var r = require('rethinkdbdash')({
  pool: false,
  cursor: true
});

If you want to take advantage of the connection pool, refer to the next section.

From the official driver

To switch from the official driver to rethinkdbdash and get the most of it, here are the few things to do:

  1. Change the way to import the driver.
var r = require('rethinkdb');

To:

var r = require('rethinkdbdash')();
// Or if you do not connect to the default local instance:
// var r = require('rethinkdbdash')({servers: [{host: ..., port: ...}]});
  1. Remove everything related to a connection:
r.connect({host: ..., port: ...}).then(function(connection) {
  connection.on('error', handleError);
  query.run(connection).then(function(result) {
    // console.log(result);
    connection.close();
  });
});

Becomes:

query.run().then(function(result) {
  // console.log(result);
});
  1. Remove the methods related to the cursor. This typically involves removing toArray:
r.table('data').run(connection).then(function(cursor) {
  cursor.toArray().then(function(result) {
    // console.log(result):
  });
});

Becomes

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

Using TLS Connections

Note: Support for a TLS proxy is experimental.

RethinkDB does not support TLS connections to the server yet, but in case you want to run it over an untrusted network and need encryption, you can easily run a TLS proxy on your server with:

var tls = require('tls');
var net = require('net');
var tlsOpts = {
  key: '', // You private key
  cert: '' // Public certificate
};
tls.createServer(tlsOpts, function (encryptedConnection) {
  var rethinkdbConn = net.connect({
    host: 'localhost',
    port: 28015
  });
  encryptedConnection.pipe(rethinkdbConn).pipe(encryptedConnection);
}).listen(29015);

And then safely connect to it with the tls option:

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

ssl may also be an object that will be passed as the options argument to tls.connect.

New features and differences

Rethinkdbdash ships with a few interesting features.

Importing the driver

When you import the driver, as soon as you execute the module, you will create a default connection pool (except if you pass {pool: false}. The options you can pass are:

  • db: <string> - The default database to use if none is mentioned.
  • user: <string> - The RethinkDB user, default value is admin.
  • password: <string> - The password for the user, default value is an empty string.
  • discovery: <boolean> - When true, the driver will regularly pull data from the table server_status to keep a list of updated hosts, default false
  • pool: <boolean> - Set it to false, if you do not want to use a connection pool.
  • buffer: <number> - Minimum number of connections available in the pool, default 50
  • max: <number> - Maximum number of connections available in the pool, default 1000
  • timeout: <number> - The number of seconds for a connection to be opened, default 20
  • pingInterval: - if > 0, the connection will be pinged every pingInterval seconds, default -1
  • timeoutError: <number> - Wait time before reconnecting in case of an error (in ms), default 1000
  • timeoutGb: <number> - How long the pool keep a connection that hasn't been used (in ms), default 60*60*1000
  • maxExponent: <number> - The maximum timeout before trying to reconnect is 2^maxExponent x timeoutError, default 6 (~60 seconds for the longest wait)
  • silent: - console.error errors, default false
  • servers: an array of objects {host: <string>, port: <number>} representing RethinkDB nodes to connect to
  • optionalRun: - if false, yielding a query will not run it, default true
  • log: - will be called with the log events by the pool master

In case of a single instance, you can directly pass host and port in the top level parameters.

Examples:

// connect to localhost:8080, and let the driver find other instances
var r = require('rethinkdbdash')({
    discovery: true
});

// connect to and only to localhost:8080
var r = require('rethinkdbdash')();

// Do not create a connection pool
var r = require('rethinkdbdash')({pool: false});

// Connect to a cluster seeding from `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},
    ]
});

// Connect to a cluster containing `192.168.0.100`, `192.168.0.100`, `192.168.0.102` and
// use a maximum of 3000 connections and try to keep 300 connections available at all time.
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
});

You can also pass {cursor: true} if you want to retrieve RethinkDB streams as cursors and not arrays by default.

Note: The option {stream: true} that asynchronously returns a stream is deprecated. Use toStream instead.

Note: The option {optionalRun: false} will disable the optional run for all instances of the driver.

Note: Connections are created with TCP keep alive turned on, but some routers seem to ignore this setting. To make sure that your connections are kept alive, set the pingInterval to the interval in seconds you want the driver to ping the connection.

Note: The error __rethinkdbdash_ping__ is used for internal purposes (ping). Do not use it.

Connection pool

As mentioned before, rethinkdbdash has a connection pool and manage all the connections itself. The connection pool is initialized as soon as you execute the module.

You should never have to worry about connections in rethinkdbdash. Connections are created as they are needed, and in case of a host failure, the pool will try to open connections with an exponential back off algorithm.

The driver execute one query per connection. Now that rethinkdb/rethinkdb#3296 is solved, this behavior may be changed in the future.

Because the connection pool will keep some connections available, a script will not terminate. If you have finished executing your queries and want your Node.js script to exit, you need to drain the pool with:

r.getPoolMaster().drain();

The pool master by default will log all errors/new states on stderr. If you do not want to pollute stderr, pass silent: true when you import the driver and provide your own log method.

r = require('rethinkdbdash')({
  silent: true,
  log: function(message) {
    console.log(message);
  }
});
Advanced details about the pool

The pool is composed of a PoolMaster that retrieve connections for n pools where n is the number of servers the driver is connected to. Each pool is connected to a unique host.

To access the pool master, you can call the method r.getPoolMaster().

The pool emits a few events:

  • draining: when drain is called
  • queueing: when a query is added/removed from the queue (queries waiting for a connection), the size of the queue is provided
  • size: when the number of connections changes, the number of connections is provided
  • available-size: when the number of available connections changes, the number of available connections is provided

You can get the number of connections (opened or being opened).

r.getPoolMaster().getLength();

You can also get the number of available connections (idle connections, without a query running on it).

r.getPoolMaster().getAvailableLength();

You can also drain the pool as mentionned earlier with;

r.getPoolMaster().drain();

You can access all the pools with:

r.getPoolMaster().getPools();

The pool master emits the healthy when its state change. Its state is defined as:

  • healthy when at least one pool is healthy: Queries can be immediately executed or will be queued.
  • not healthy when no pool is healthy: Queries will immediately fail.

A pool being healthy is it has at least one available connection, or it was just created and opening a connection hasn't failed.

r.getPoolMaster().on('healthy', function(healthy) {
  if (healthy === true) {
    console.log('We can run queries.');
  }
  else {
    console.log('No queries can be run.');
  }
});
Note about connections

If you do not wish to use rethinkdbdash connection pool, you can implement yours. The connections created with rethinkdbdash emits a "release" event when they receive an error, an atom, or the end (or full) sequence.

A connection can also emit a "timeout" event if the underlying connection times out.

Arrays by default, not cursors

Rethinkdbdash automatically coerce cursors to arrays. If you need a raw cursor, you can call the run command with the option {cursor: true} or import the driver with {cursor: true}.

r.expr([1, 2, 3]).run().then(function(result) {
  console.log(JSON.stringify(result)) // print [1, 2, 3]
})
r.expr([1, 2, 3]).run({cursor: true}).then(function(cursor) {
  cursor.toArray().then(function(result) {
    console.log(JSON.stringify(result)) // print [1, 2, 3]
  });
})

Note: If a query returns a cursor, the connection will not be released as long as the cursor hasn't fetched everything or has been closed.

Readable streams

Readable streams can be synchronously returned with the toStream([connection]) method.

var fs = require('fs');
var file = fs.createWriteStream('file.txt');

var r = require('rethinkdbdash')();
r.table('users').toStream()
  .on('error', console.log)
  .pipe(file)
  .on('error', console.log)
  .on('end', function() {
    r.getPool().drain();
  });

Note: The stream will emit an error if you provide it with a single value (streams, arrays and grouped data work fine).

Note: null values are currently dropped from streams.

Writable and Transform streams

You can create a Writable or Transform streams by calling toStream([connection, ]{writable: true}) or toStream([connection, ]{transform: true}) on a table.

By default, a transform stream will return the saved documents. You can return the primary key of the new document by passing the option format: 'primaryKey'.

This makes a convenient way to dump a file your database.

var file = fs.createReadStream('users.json')
var table = r.table('users').toStream({writable: true});

file.pipe(transformer) // transformer would be a Transform stream that splits per line and call JSON.parse
    .pipe(table)
    .on('finish', function() {
        console.log('Done');
        r.getPool().drain();
    });

Optional run with yield

The then and catch methods are implemented on a Term - returned by any methods like filter, update etc. They are shortcut for this.run().then(callback) and this.run().catch(callback).

This means that you can yield any query without calling run.

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

bluebird.coroutine(function*() {
  try {
    var result = yield r.table('users').get('[email protected]').update({name: 'Michel'});
    assert.equal(result.errors, 0);
  } catch(err) {
    console.log(err);
  }
});

Note: You have to start Node >= 0.11 with the --harmony flag.

Global default values

You can set the maximum nesting level and maximum array length on all your queries with:

r.setNestingLevel(<number>)
r.setArrayLimit(<number>)

Undefined values

Rethinkdbdash will ignore the keys/values where the value is undefined instead of throwing an error like the official driver.

Better errors

Backtraces

If your query fails, the driver will return an error with a backtrace; your query will be printed and the broken part will be highlighted.

Backtraces in rethinkdbdash are tested and properly formatted. Typically, long backtraces are split on multiple lines and if the driver cannot serialize the query, it will provide a better location of the error.

Arity errors

The server may return confusing error messages when the wrong number of arguments is provided (See rethinkdb/rethinkdb#2463 to track progress). Rethinkdbdash tries to make up for it by catching errors before sending the query to the server if possible.

Performance

The tree representation of the query is built step by step and stored which avoid recomputing it if the query is re-run.

The code was partially optimized for v8, and is written in pure JavaScript which avoids errors like issue #2839

Run tests

Update test/config.js if your RethinkDB instance doesn't run on the default parameters.

Make sure you run a version of Node that supports generators and run:

npm test

Longer tests for the pool:

mocha long_test/discovery.js -t 50000
mocha long_test/static.js -t 50000

Tests are also being run on wercker:

FAQ

  • Why rethinkdbdash?

    Rethinkdbdash was built as an experiment for promises and a connection pool. Its purpose was to test new features and improve the official driver. Today, rethinkdbdash still tries to make the developer experience as pleasant as possible - like with the recent support for Node.js streams.

    Some features like promises have been back ported to the official driver, some like the connection pool and streams are on their way.

  • Is it stable?

    Yes. Rethinkdbdash is used by quite many people. The driver is also used by thinky, and has been and is still being tested in the wild.

  • Does it work with io.js?

    All the tests pass with io.js so yes.

  • Is rethinkdbdash going to become the JavaScript official driver?

    Not (yet?), maybe :)

    Completely replacing the driver requires some work:

    • Integrate the driver in RethinkDB suite test.
    • Support HTTP connections.
    • Rollback some default like the coercion of cursors to arrays.
  • Can I contribute?

    Feel free to send a pull request. If you want to implement a new feature, please open an issue first, especially if it's a non backward compatible one.

Browserify

To build the browser version of rethinkdbdash, run:

node browserify.js

rethinkdbdash's People

Contributors

aleclarson avatar andrerpena avatar azazdeaz avatar christophehurpeau avatar danielmewes avatar dunklestoast avatar feego avatar frankleng avatar joaojeronimo avatar kristjantammekivi avatar kulbirsaini avatar markherhold avatar marshall007 avatar marsup avatar mbroadst avatar mkozjak avatar neumino avatar sagivf avatar samuelgoldenbaum avatar weshoke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rethinkdbdash's Issues

indexCreate with r.branch gives [RqlDriverError: Nesting depth limit exceeded]

I'm pretty sure this is a driver error, because it works in the web UI, but from rethinkdbdash, this code gives the error (haven't really had time to isolate – I don't know if it's the multi, or if it's r.branch, or what it is – but it definitely doesn't work):

r.db('a').table('b').indexCreate('c', function(b) {
    return r.branch(
        b('something'),
        ['a'],
        ['b']
    );
}, { multi: true })

.toISO8601(), .toEpochTime() returns a function

I believed those functions are supposed to return String and Number value but not a function.

For example, when I put "r.now().toEpochTime()" in my code and display it in console.log, it is not showing a number but a function.

ps. All .minutes(), minutes(), .month(), .seconds(), .timeOfDay(), .toEpochTime(), .toISO8601() return a function.

I haven't tried the newest version yet, I'm on the rethinkdbdash ver 1.12.13.

Thank you.

Add events to pool.

It would be great if the connection pool emitted events, such as "open", "close", and another when a query is run. This would help with tracing, checking for leaks, etc.

v1.13

The JSON protocol is implemented in the v1.13 branch.

I need to add feeds + a few terms.
The tricky part will be to do r.args without sending poor backtraces, but I think I have a good idea on how to do it.

Will try to ship that today.

rethinkdbdash-unstable breaking with 0.11.13

Not sure if this is a known issue; can post stack trace if requested.
rethinkdbdash-unstable works fine in 0.11.12, but on 0.11.13 it's breaking.

In the README it mentions 0.11.9 and 0.11.10, but it works up to 0.11.12 as far as I can tell. Maybe update package.json to specify node version GTE 0.11.9 and LT 0.11.13?

Could be a node-protobuf issue, since it crashes when trying to build it.

Cannot insert nested document that contains r.now() or a Date object

The following throws an error:

var r = require('rethinkdbdash')({
    db: 'test',
    min: 0,
    max: 1,
    bufferSize: 0
});

r.table('test').insert({
    field: 'test',
    field2: { nested: 'test' },
    date: r.now()
}).run().finally(function () {
        r.getPool().drain();
    });

Error:

> node test.js

/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:817
    if (expression === undefined) throw new Error.ReqlDriverError("Cannot conv
                                        ^
ReqlDriverError: Cannot convert `undefined` with r.expr().
    at Term.expr (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:817:41)
    at new Json (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:2462:30)
    at Term.json (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:877:12)
    at Term._exprJSON (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:958:68)
    at Term.exprJSON (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:883:23)
    at new Insert (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:2476:32)
    at Term.insert (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:218:12)
    at Object.<anonymous> (/Users/jason/test/test.js:8:17)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)

While both of the following work fine:

var r = require('rethinkdbdash')({
    db: 'test',
    min: 0,
    max: 1,
    bufferSize: 0
});

r.table('test').insert({
    date: r.now()
}).run().finally(function () {
        r.getPool().drain();
    });
var r = require('rethinkdbdash')({
    db: 'test',
    min: 0,
    max: 1,
    bufferSize: 0
});

r.table('test').insert({
    field: 'test',
    field2: { nested: 'test' }
}).run().finally(function () {
        r.getPool().drain();
    });

Syntactic sugar for joins

I've been a doing a lot of queries like this:

r.table("users").eqJoin("session_id", r.table("sessions"))
                            .pluck({
                                left: true,
                                right: ['field1', 'field2']
                            }).zip()

I don't know if this fits rethinkdbdash API, but it would be very nice to do something like:

r.table("users").join("sessions", {
                                left: true,
                                right: ['field1', 'field2']
                            })

r.not doesn't work

.filter(function(order) { return r.not(order.hasFields('test')) })

2014-05-16T00:51:06.012Z - error: TypeError: Object [object Function] has no method 'not'

so, I did .filter(function(order) { return order.hasFields('test').not() })

2014-05-16T01:08:38.339Z - error: TypeError: Object [object Function] has no method 'not'
    at Function.<anonymous>
    at new Func (rethinkdbdash/lib/term.js:1150:20)
    at Term.expr (rethinkdbdash/lib/term.js:825:16)
    at new Filter (rethinkdbdash/lib/term.js:1367:32)
    at Term.filter (rethinkdbdash/lib/term.js:319:12)

New connections for .changes

Just a quick question about the implications of the built-in connection pooling with this library. The documentation for the official driver's .changes() says:

It's usually a good idea to open changefeeds on their own connection. If you don't, other queries run on the same connection will experience unpredictable latency spikes while the connection blocks on more changes.

Since rethinkdbdash uses a connection pool by default, does this mean we can leave that up to the library and safely use .changes and other queries on the same r instance? Or should we still be using a dedicated instance for the change feed?

How is connection pooling relevant compared to original driver

I have tested rethinkdbdash versus original driver and found no performance difference.

I thought that connection pooling would help but it seems to not make any difference.

Can you provide me some background on how connection pooling would be interesting in comparison to the original driver?

Thanks

Question/suggestion concerning connection pool reuse

Typically I set up my projects to have each model (DB entity) in it's own file. If I require and instantiate rethinkdbdash from within each of those modules, each instance will create its own connection pool, correct?

What's the best practice in this scenario? Is there a way to share the same connection pool across instances or do I need to create a configuration module to share a single instance across my application?

Before rethinkdbdash came along, I was using guillaumervls/rql-promise which handled this pretty nicely:

// file: server.js
var rql = require('rql-promise');

// call rql.connect() once during app
// initialization and you're done
rql.connect({
  host: 'localhost',
  db: 'test'
});
// file: models/foo.js
var rql = require('rql-promise');

// no need to instantiate anything
// or call rql.connect() again
rql(r.table('foo'))

Connection Reset

I'm trying to insert 20k rows into the database, where I do 3 at a time with this current config:

var r = require('rethinkdbdash')({
// var r = require('rethinkdbdash-unstable')({
  min: 100, // minimum number of connections in the pool, default 50
  max: 10000, // maximum number of connections in the pool, default 1000
  bufferSize: 100, // minimum number of connections available in the pool, default 50
  timeoutError: 1000, // wait time before reconnecting in case of an error (in ms), default 1000
  timeoutGb: 60 * 60 * 1000, // how long the pool keep a connection that hasn't been used (in ms), default 60*60*1000
  host: '127.0.0.1',
  port: 28015,
  db: 'ml'
});
var doParallel = [];
while (data.length) {
  doParallel.push(r.table('samples').insert(r.json(JSON.stringify(data.splice(0, 3)))).run());
}
return yield doParallel;

When I run this query it's going to do about 6667 inserts in "parallel". When I do this I get this error a few hundred times:

Fail to create a new connection for the connection pool The error returned was:
Failed to connect to 127.0.0.1:28015
Full error:
{
  "code": "ECONNRESET",
  "errno": "ECONNRESET",
  "syscall": "connect"
}.
ReqlDriverError
    at Socket.<anonymous> (/Users/nick/Dropbox/projects/ml-api/node_modules/rethinkdbdash/lib/connection.js:63:16)
    at Socket.g (events.js:199:16)
    at Socket.EventEmitter.emit (events.js:107:17)
    at net.js:436:14
    at process._tickDomainCallback (node.js:372:11)

However, it seems to still insert the 20k rows into the database correctly. I'm wondering if I'm spamming the pool too fast or if you might have any suggestions?

Since it does seem to insert the data correctly, it would be nice to be able to disable the error output.

each(callback[, onFinishedCallback]) - onFinishedCallback doesn't get called on premature

I don't think each() is following the api:

http://www.rethinkdb.com/api/javascript/each/

"The second callback is optional and is called when the iteration stops (when there are no more rows or when the callback returns false"

In this example "done" never gets printed.

co(function * () {
  var cursor = yield r.db('test').table('example').run();
  cursor.each(function(err, row) {
    if (err) console.log('err: %j', err);
    console.log('got row: %j', row);
    return false;
  }, function() {
    console.log('done');
  })
})();

Advanced tests for the pool

There should be some tests for things like:

#48
#49

I have a fix for these two issues, and while it should work, it's kind of a pain to manually test. We should spin up fake servers (like what's written on reqlite), or mock some connections objects, not sure what's the most convenient here.

`r.do` is not implemented?

Hey,

Is r.do missing from this lib? I'm getting this error when trying to use r.do ...

TypeError: Object function (x) {
        return new Term(_r).expr(x);
    } has no method 'do'
    at repl:2:21
    at GeneratorFunctionPrototype.next (native)
    at next (/Users/chrismcc/workspace/ti-node/node_modules/co/index.js:77:21)
    at /Users/chrismcc/workspace/ti-node/node_modules/co/index.js:50:5
    at repl:4:3
    at REPLServer.defaultEval (repl.js:129:27)
    at bound (domain.js:271:14)
    at REPLServer.runBound [as eval] (domain.js:284:12)
    at Interface.<anonymous> (repl.js:277:12)
    at Interface.EventEmitter.emit (events.js:101:17)

Here's what I am running...

var co = require('co');
var rethinkdbdash = require('rethinkdbdash-unstable');
var r = rethinkdbdash();

co(function *() {
  var res = yield r.do(r.expr(1)).run();
  console.log('RES', res);
})();

r.do(r.expr(1)) works fine in, e.g., the Data Explorer.

Thanks!!! 🌟

indexCreate with multi broken?

Hey, just FYI, indexCreate with the multi option seems broken in rethinkdbdash, e.g.

  yield r.table('bundles').indexCreate('courseIds', {multi: true}).run();

returns:

    ReqlRuntimeError: Expected type FUNCTION but found DATUM:
{
    "multi":    true
} in:
r.table("bundles").indexCreate("courseIds", {
                                            ^
    multi: true
    ^^^^^^^^^^^
})
^ 
ReqlRuntimeError
    at Connection._processResponse (/Users/chrismcc/workspace/xxx/node_modules/rethinkdbdash/lib/connection.js:155:35)
    at Socket.<anonymous> (/Users/chrismcc/workspace/xxx/node_modules/rethinkdbdash/lib/connection.js:91:22)
    at Socket.EventEmitter.emit (events.js:101:17)
    at readableAddChunk (_stream_readable.js:156:16)
    at Socket.Readable.push (_stream_readable.js:123:10)
    at TCP.onread (net.js:509:20)
From previous event:
    at new Promise (/Users/chrismcc/workspace/xxx/node_modules/rethinkdbdash/node_modules/bluebird/js/main/promise.js:95:37)
    at Term.run (/Users/chrismcc/workspace/xxx/node_modules/rethinkdbdash/lib/term.js:79:21)

This seems to work with, e.g., recli which uses the official rethinkdb driver.

recli> r.db('ti_development').table('bundles').indexCreate('courseIds', {multi: true})
{ created: 1 }

How to drain the pool and stop backoff connection attempts?

I'm trying to handle the situation where the database is unavailable on startup. I've added timeouts which call .drain() after some delay, if no connections are added during that time (as determined by listening for available-size events.)

That all works great, but when I call .drain(), it seems that the connections which were never established in the first place keep attempting. I need to them stop so the process will gracefully exit. But it looks like the exponential backoff code doesn't attempt to check if the pool is currently draining / drained.

Any suggestions? Happy to submit a PR adding a check for _draining === null in the backoff function (or in createConnection itself?) but wanted to get your take first.

Semi-related to #39


Edit: Looks like there is more than one place where that exponential backoff happens, and the one I linked to isn't the one executing in my case. But the general point stands.

sequences return raw time format instead of native

Hi,

Spent my afternoon tracking down this weird bug...

var co = require('co');
var rethinkdbdash = require('rethinkdbdash-unstable');
var r = rethinkdbdash({db: 'test'});

co(function *() {
  yield r.tableCreate('testing').run();
  yield r.table('testing').indexCreate('companyId').run();
  yield r.table('testing').insert({companyId: '1', createdAt: r.now()}).run();
  var cursor = yield r.table('testing').getAll('1', {index: 'companyId'}).run({timeFormat: 'native'});
  var result = yield cursor.toArray();
  console.log('result', result);
})();

Result is:

result [ { companyId: '1',
    createdAt: 
     { '$reql_type$': 'TIME',
       epoch_time: 1397950623.646,
       timezone: '+00:00' },
    id: '0a3beb01-fb42-4e80-9eb7-c2d4be17439e' } ]

Notice the time format is raw, even though I am specifying native. Leaving timeFormat unspecified (e.g. just .run()) should default to native, but still returns a raw time.

This seems to happen anytime I get a sequence back. I believe we're just missing a call to pb.convertPseudoType somewhere in here: https://github.com/neumino/rethinkdbdash/blob/master/lib/protobuf.js#L90-L97

Node v0.11.10
rethinkdbdash v1.12.4

How can I use noReplyWait() with rethinkdbdash?

Suppose I'm running inserts with noreply: true and somewhere I want to query but first use noReplyWait. How do I do this with rethinkdbdash? I've already connected on the framework initialization and have the r instance available on my middlewares

TypeError: undefined is not a function

When I try to set the min connections on the pool to 100 I get a TypeError: undefined is not a function. Which is probably not the desired behavior. Obviously I don't get this error once I set bufferSize: 100.

My config:

var r = require('rethinkdbdash')({
// var r = require('rethinkdbdash-unstable')({
  min: 100, // minimum number of connections in the pool, default 50
  max: 10000, // maximum number of connections in the pool, default 1000
  bufferSize: 50, // minimum number of connections available in the pool, default 50
  timeoutError: 1000, // wait time before reconnecting in case of an error (in ms), default 1000
  timeoutGb: 60 * 60 * 1000, // how long the pool keep a connection that hasn't been used (in ms), default 60*60*1000
  host: '127.0.0.1',
  port: 28015,
  db: 'ml'
});
/Users/nick/Dropbox/projects/ml-api/node_modules/rethinkdbdash/lib/pool.js:29
    if (this.options.min > this.options.bufferSize) throw new Error.ReqlDriver
                                                          ^
TypeError: undefined is not a function
    at new Pool (/Users/nick/Dropbox/projects/ml-api/node_modules/rethinkdbdash/lib/pool.js:29:59)
    at r.createPool (/Users/nick/Dropbox/projects/ml-api/node_modules/rethinkdbdash/lib/index.js:69:18)
    at module.exports (/Users/nick/Dropbox/projects/ml-api/node_modules/rethinkdbdash/lib/index.js:287:36)
    at Object.<anonymous> (/Users/nick/Dropbox/projects/ml-api/lib/r.js:5:33)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:349:32)
    at Function.Module._load (module.js:305:12)
    at Module.require (module.js:357:17)
    at require (module.js:373:17)

Browser support

The official driver runs in the browser. Is there any way to get rethinkdbdash to run in the browser, perhaps with Browserify?

Currently I get 'Error: Cannot find module '/node_modules/rethinkdbdash/lib/helper.js' when requiring rethinkdbdash and building with Browserify.

r.now() usage?

How does one use r.now() with rethinkdbdash?
I tried like this (according to RQL official docs):

var file = {
        originalName: form.fields.name,
        path: 'xyz',
        creationDate: r.now()
    };
yield r.table('table').insert(file).run();

and like this (got this from the tests):

var file = {
        originalName: form.fields.name,
        path: 'xyz',
        creationDate: yield r.now().run()
    };
yield r.table('table').insert(file).run();

Using the first version the creationDate property is a function, in the second version it is a date.
However, no matter which version I use I'm always getting the following error:

ReqlDriverError
    at Term.expr (/home/usr/project/node_modules/rethinkdbdash/lib/term.js:780:41)
    at new Json (/home/usr/project/node_modules/rethinkdbdash/lib/term.js:2363:30)
    at Term.json (/home/usr/project/node_modules/rethinkdbdash/lib/term.js:840:12)
    at Term._exprJSON (/home/usr/project/node_modules/rethinkdbdash/lib/term.js:922:66)
    at Term.exprJSON (/home/usr/project/node_modules/rethinkdbdash/lib/term.js:846:23)
    at new Insert (/home/usr/project/node_modules/rethinkdbdash/lib/term.js:2377:32)
    at Term.insert (/home/usr/project/node_modules/rethinkdbdash/lib/term.js:214:12)
    at save (/home/usr/project/file.js:25:28)

Am I just not using r.now() right or is there something else not working right?

The pool does not have any opened connections and failed to open a new one.

Currently, there seems to be a memory leak problem with rethinkdb, which is causing it to crash and gives me a unique opportunity to see what happens to the pool when the database goes down.

Every time rethinkdb crashes and restarts, the pool doesn't seem to ever reconnect, --even after rethinkdb has been restarted. All I get are these errors: ReqlDriverError: The pool does not have any opened connections and failed to open a new one.

Best way to close() the pool?

Whats the best way to close() the pool?

I see in the documentation r.getPool().drain(); is this what I'm looking for?

I want to be able to call it and when it's closed, have the program automatically end because there's no connections open.

Does not exit after calling tableCreate

It looks like something related to r.tableCreate() is keeping a timer or a connection or something open when I'm using the promises and co.

https://gist.github.com/mkleehammer/050c8e9a782edbf4c7e0

I'm just now learning the driver and RethinkDB so I might have missed something obvious, but there's not a lot of code in that example. All I do is create the table "mktest" and the script won't exit, even after calling r.getPool().drain().

What am I missing? Thanks.

Downgrading for Node 0.10.26

I don't really know when the next stable release is coming...

I'll just change the dependency of node-protobuf to the stable one and release two packages (rethinkdbdash for node 0.10.26, and rethinkdbdash-unstable for node 0.11.10).

I would have to update all the tests though, which is going to take some time.

authKey not working

I'm absolutely sure I'm passing in the correct key:

var r = require('rethinkdbdash')({ host: 'localhost', port: 28015, authKey: 'MY AUTH KEY' });

I get:

Fail to create a new connection for the connection pool The error returned was:
Server dropped connection with message: "ERROR: incorrect authorization key
".
ReqlDriverError
    at Socket.<anonymous> (/Users/dmitrig01/Documents/Projects/Kindred-API/rethinkdb-schema/node_modules/rethinkdbdash/lib/connection.js:71:32)
    at Socket.EventEmitter.emit (events.js:98:17)
    at readableAddChunk (_stream_readable.js:156:16)
    at Socket.Readable.push (_stream_readable.js:123:10)
    at TCP.onread (net.js:509:20)

(I tried resetting the key, with rethinkdb admin set auth a, and passing in authKey a, but that doesn't work; if I do rethinkdb admin unset auth and don't pass in a key, it works)

HTTP API support spec

For my RethinkDB usecase, use over HTTP is an important characteristic, and I am willing to build a HTTP API client for rethinkdbdash.

Currently, I need to know modifications need to be made to rethinkdbdash?
The only other queries I currently have are:

  • What type encoding does the current ReDB HTTP API use?
  • What are the differences between the HTTP before and after the removal of protobuf encoding?
  • If there were HTTP protocol differences after the removal of the protobuf encoding step, does rethinkdbdash have to be compatible with versions <1.12?

[1.12] Grouping by index is not supported?

Simple example which works fine in the data explorer:

r.db('test').table('orders').group({ index: 'user' })

Results in:

ReqlRuntimeError: Expected type STRING but found OBJECT. in:
r.db("test").table("orders").group({
                                   ^
    index: "user"
    ^^^^^^^^^^^^^
})

Prod mode

The drive should have two mode, prod and dev (which we should be able to set per query in run).
In prod, these queries should print a warning (the first time) and suggest to use an index.

r.table("posts").orderBy("field")
r.table("posts").filter({field: "value"})
r.table("posts").group("date")

The question are:

  • What the default should be?
  • Can we catch some filter that should be between too?

Note: Accidentally opened on rethinkdb -_-
rethinkdb/rethinkdb#3247

Cannot install in v0.10.26

$ npm install --save rethinkdbdash
npm http GET https://registry.npmjs.org/rethinkdbdash
npm http 304 https://registry.npmjs.org/rethinkdbdash
npm http GET https://registry.npmjs.org/node-protobuf
npm http 304 https://registry.npmjs.org/node-protobuf

> [email protected] install ./node_modules/rethinkdbdash/node_modules/node-protobuf
> node-gyp rebuild

  CXX(target) Release/obj.target/protobuf/protobuf.o
../protobuf.cpp:34:29: error: no type named 'FunctionCallbackInfo' in namespace 'v8'
  static void New(const v8::FunctionCallbackInfo<Value> &args);
                        ~~~~^
../protobuf.cpp:34:49: error: expected ')'
  static void New(const v8::FunctionCallbackInfo<Value> &args);
                                                ^
../protobuf.cpp:34:18: note: to match this '('
  static void New(const v8::FunctionCallbackInfo<Value> &args);
                 ^
../protobuf.cpp:35:35: error: no type named 'FunctionCallbackInfo' in namespace 'v8'
  static void Serialize(const v8::FunctionCallbackInfo<Value> &args);
                              ~~~~^

etc

Add an option for the pool to log errors

The pool now uses console.log to dump errors.

https://github.com/visionmedia/debug was mentioned here #29
I'm not sure that's really what people want (it's pretty though).

I was thinking of letting people provide a stream where the pool would write, something similar to the options in child_process.spawn.
By default it would just log things with console.log.

coerceTo('ARRAY') does not work

I cannot get coerceTo('ARRAY') to work with rethinkdbdash in any kind of query. It always returns a cursor.

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

r.dbList().coerceTo('array').run()
  .then(function (dbList) {
    assert(Array.isArray(dbList), 'dbList should be an array');
    assert(typeof dbList.toArray !== 'function', 'toArray should not exist, because tableList should not be a cursor');
  });
Possibly unhandled AssertionError: dbList should be an array
    at /Users/jason/test/test.js:6:4
From previous event:
    at new Promise (/Users/jason/test/node_modules/bluebird/js/main/promise.js:82:37)
    at Term.run (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:90:21)
    at Object.<anonymous> (/Users/jason/test/test.js:4:30)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
Possibly unhandled AssertionError: toArray should not exist, because tableList should not be a cursor
    at /Users/jason/test/test.js:6:4
From previous event:
    at new Promise (/Users/jason/test/node_modules/bluebird/js/main/promise.js:82:37)
    at Term.run (/Users/jason/test/node_modules/rethinkdbdash/lib/term.js:90:21)
    at Object.<anonymous> (/Users/jason/test/test.js:4:30)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

rethinkdbdash @ 1.13.12
rethinkdb @ 1.13.3

Add syntactic sugar to get array instead of cursor

I'm using this lib with koa and it's annoying to have to yield twice to get the full array.

I would love a way to yield just once and have it return the full array. I'm unsure of what the best syntax for this would be, but something like the following would be great:

let arr = yield r.expr([1, 2, 3]).run().toArray();
console.log(arr); // print [1,2,3]

In the case of someone yielding on something that returns a single value, perhaps it would just return an array with the item?

let arr = yield r.expr(1).run().toArray();
console.log(arr); // print [1]

I'm willing to look into it and attempt creating a PR if you'd be interested in it. I'm also flexible on the syntax for it, I chose adding .toArray() at the end because it's very similar to what's already available.

Fancy quotes upon insert with `returnVals: true` yields "ReqlClientError: Client is buggy (failed to deserialize query)."

Pretty simple, seems like a encoding issue with regards to fancy quotes, e.g.

To reproduce: yield r.table('topics').insert({caption: '“'}, {returnVals: true}).run()

ReqlClientError: Client is buggy (failed to deserialize query).
    at Connection._processResponse (/Users/chrismcc/workspace/ti-node/node_modules/rethinkdbdash/lib/connection.js:144:35)
    at Socket.<anonymous> (/Users/chrismcc/workspace/ti-node/node_modules/rethinkdbdash/lib/connection.js:102:22)
    at Socket.EventEmitter.emit (events.js:107:17)
    at readableAddChunk (_stream_readable.js:159:16)
    at Socket.Readable.push (_stream_readable.js:126:10)
    at TCP.onread (net.js:514:20)
From previous event:
    at new Promise (/Users/chrismcc/workspace/ti-node/node_modules/rethinkdbdash/node_modules/bluebird/js/main/promise.js:82:37)
    at Term.run (/Users/chrismcc/workspace/ti-node/node_modules/rethinkdbdash/lib/term.js:90:21)
    at /Users/chrismcc/workspace/ti-node/test.js:5:98
    at GeneratorFunctionPrototype.next (native)
    at next (/Users/chrismcc/workspace/ti-node/node_modules/co/index.js:83:21)
    at /Users/chrismcc/workspace/ti-node/node_modules/co/index.js:56:5
    at Object.<anonymous> (/Users/chrismcc/workspace/ti-node/test.js:6:3)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)
    at Module.load (module.js:349:32)
    at Function.Module._load (module.js:305:12)
    at Function.Module.runMain (module.js:490:10)
    at startup (node.js:124:16)
    at node.js:807:3'

I think this is an issue with rethinkdbdash because the same query works fine in the data explorer.

Optimize code for v8

I just ran a little script to profile the driver.

Results:
timer-events

Non optimized functions:

LazyCompile: ~<anonymous> /home/michel/projects/rethinkdb-all/rethinkdbdash/lib/term.js:80:51

LazyCompile: tryCatch1 /home/michel/projects/rethinkdb-all/rethinkdbdash/node_modules/bluebird/js/main/util.js:62:19

LazyCompile: ~pb.makeDatum /home/michel/projects/rethinkdb-all/rethinkdbdash/lib/protobuf.js:42:24

LazyCompile: ~Connection._processResponse /home/michel/projects/rethinkdb-all/rethinkdbdash/lib/connection.js:109:49

LazyCompile: Term.expr /home/michel/projects/rethinkdb-all/rethinkdbdash/lib/term.js:773:31

LazyCompile: Term.db /home/michel/projects/rethinkdb-all/rethinkdbdash/lib/term.js:258:29

LazyCompile: Term.table /home/michel/projects/rethinkdb-all/rethinkdbdash/lib/term.js:263:32

LazyCompile: r.table /home/michel/projects/rethinkdb-all/rethinkdbdash/lib/index.js:88:29

So nothing unexpected:

  • I'll wrap some code when there is a for(x in y)
  • I may not change __proto__ on the fly, and therefore depreciate r(...) (if the performance gain appear to be non negligible)

r.use() usage

Once I've imported and instantiated the module: var r = require('rethinkdbdash')(), is there a way I can set the db on all the connections in the pool or do I have to recreate the pool? Seems like I should be able to do r.use('testdb') and it will set everything in the pool to use that database.

My use case for this is when I'm running tests, I tend to instantiate the module without the database because it hasn't been created yet. Once the "test" database is created, from that point on, I want to use the test database but I shouldn't have to re-instantiate (because that would require me to call pool.drain(), wait for it, and then re-instantiate).

`cursor.toArray()` hanging on complex query

Sorry for the barrage today.

This query works in the data explorer, but hangs on yield cursor.toArray(); within rethinkdbdash.

r.db('ti_development').table('courses').getAll('cde178e3-4c82-4918-b022-9042c3ace84c', {index: 'company'}).map(function(course) {
  return r.object(
    'course', course,
    'sections', r.branch(course('sections').count().eq(0), [], r.db('ti_development').table('sections').getAll(r.args(course('sections'))).coerceTo('ARRAY'))
  ).merge(function(hash) {
    return r.object('lessons', hash('sections').concatMap(function(section) { return section('lessons'); }).do(function(lessons) {
      return r.branch(lessons.count().eq(0), [], r.db('ti_development').table('lessons').getAll(r.args(lessons)).coerceTo('ARRAY'));
    }));
  }).merge(function(hash) {
    return r.object('topics', hash('lessons').concatMap(function(lesson) { return lesson('topics')('id'); }).do(function(topics) {
      return r.branch(topics.count().eq(0), [], r.db('ti_development').table('topics').getAll(r.args(topics)).coerceTo('ARRAY'));
    }));
  });
});

Full query wrapped in co: https://gist.github.com/chrisvariety/68a13224fc15922217d9

Any thoughts? Specifically it's the last .merge() that causes the hang -- removing that makes rethinkdbdash hang-free. And specifically it's directly related to the data, as different ids do not hang with the exact same query.

Happy to email the data set to you (it is very tiny) so you can reproduce, just let me know your email...

Thanks!!

Inserting date object property fails

This is a modified version of test/stable.js to illustrate the issue I am having inserting objects with Date objects as properties. Note the added "birthdate" property.

 40     it("Insert", function(done) {
 41         r.db(dbName).table(tableName).insert([{name: "Michel", age: 27, birthdate: new Date()}, {name: "Sophie", age: 23}]).run().then(function(result) {
 42             assert.deepEqual(result.inserted, 2);
 43             done();
 44         }).error(function(error) {
 45             done(error);
 46         })
 47     })

Here is the first failure when I run npm test.

  1)  Insert:
     TypeError: Cannot read property 'type' of undefined
      at Term._noPrefix (/Users/rob/nextgxdx/rethinkdbdash/lib/term.js:1036:20)
      at Term.json (/Users/rob/nextgxdx/rethinkdbdash/lib/term.js:876:10)
      at Term._exprJSON (/Users/rob/nextgxdx/rethinkdbdash/lib/term.js:936:48)
      at Term.exprJSON (/Users/rob/nextgxdx/rethinkdbdash/lib/term.js:883:23)
      at new Insert (/Users/rob/nextgxdx/rethinkdbdash/lib/term.js:2476:32)
      at Term.insert (/Users/rob/nextgxdx/rethinkdbdash/lib/term.js:218:12)
      at Context.<anonymous> (/Users/rob/nextgxdx/rethinkdbdash/test/stable.js:41:39)
      at Test.Runnable.run (/Users/rob/nextgxdx/rethinkdbdash/node_modules/mocha/lib/runnable.js:196:15)
      at Runner.runTest (/Users/rob/nextgxdx/rethinkdbdash/node_modules/mocha/lib/runner.js:374:10)
      at /Users/rob/nextgxdx/rethinkdbdash/node_modules/mocha/lib/runner.js:452:12
      at next (/Users/rob/nextgxdx/rethinkdbdash/node_modules/mocha/lib/runner.js:299:14)
      at /Users/rob/nextgxdx/rethinkdbdash/node_modules/mocha/lib/runner.js:309:7
      at next (/Users/rob/nextgxdx/rethinkdbdash/node_modules/mocha/lib/runner.js:247:23)
      at Object._onImmediate (/Users/rob/nextgxdx/rethinkdbdash/node_modules/mocha/lib/runner.js:276:5)
      at processImmediate [as _immediateCallback] (timers.js:330:15)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.