RoachJS - CockroachDB Driver
Introduction
This client is a port from the original Golang client.
Internally it's is more or less the same, but this driver provides a friendlier javascript interface.
Installation
$ npm install roachjs
Documentation
- Examples
- Interface
- new Client(opts)
- .get(key, callback)
- .put(key, value, callback)
- .conditionalPut(key, value, ifValue, callback)
- .increment(key, increment, callback)
- .contains(key, callback)
- .scan(start_key, end_key, limit, callback)
- .delete(key, callback)
- .deleteRange(start_key, end_key, limit, callback)
- .prepare()
- .runTransaction(opts, transaction, callback)
- Extra
Examples
Initiating a client
var Roach = require('roachjs')
var client = new Roach({
uri: 'https://localhost:8080'
})
module.exports = client
Basic client usage I
client.get("sample_key", function(err, value, res) {
if(err) throw err
client.put("other_key", value, function(err, res) {
if(err) {
}
else {
}
})
})
Advanced client usage I (Prepare & Flush)
var c = client.prepare()
c.get("sample_key", function(err, value, res) {
if(err) throw err
})
c.get("sample_key2", function(err, value, res) {
if(err) throw err
})
c.put("some_key", "some_value", function(err) {
if(err) throw err
})
c.flush(function(err, res) {
if(err) throw err
console.log('Sucessfuly flushed %d queries.', res.responses.length)
})
Advanced client usage II (Transactions)
var opts = {
name: "transaction example",
}
var errNoApples = new Error('Insufficient apples!')
var transaction = function(txn, commit, abort) {
txn.get("applesInStock", function(err, value, res) {
if(err || applesInStock.err) {
return abort(err)
}
var dispatch = 5
var inStock = parseInt(applesInStock.value)
if(inStock < dispatch) {
return abort(errNoApples)
}
txn = txn.prepare()
txn.increment("applesInStock", -dispatch)
txn.increment("applesInRoute", +dispatch)
commit()
})
}
client.runTransaction(opts, transaction, function(err, res) {
if(err === errNoApples) {
}
else if(err) {
}
else {
}
})
Interface
new Client(opts)
Returns a new roachjs client with options.
Parameters
name |
type |
description |
opts |
object |
see |
Client options
opt |
description |
default |
uri |
uri to the cockroach http endpoint |
https://localhost:8080/ |
host |
host or ip to the cockroach http endpoint |
localhost |
port |
port to the cockroach http endpoint |
8080 |
ssl |
connect throught https |
true |
user |
user to run the requests with |
root |
retry |
retry requests when cockroach responds with a busy signal |
true |
http |
http module to use |
require('https') |
agent |
http agent to use on the requests (read more) |
new http.Agent() |
clock |
clock module to use (read more) |
internal clock module |
Methods
client.get(key, callback)
Gets a single entry from the datastore, specified by key
.
Parameters
name |
type |
description |
key |
string |
|
callback |
callback |
function(err, value, res) {} |
Callback
name |
type |
description |
err |
Error() |
|
value |
Buffer |
|
res |
object |
see |
Example
client.get("key", function(err, value, res) {})
client.put(key, value, callback)
Puts a value in the datastore in the specified key
. Ideally you
should send in buffers, but you can pass a string, preferably an utf-8 encoded string.
Parameters
name |
type |
description |
key |
string |
|
value |
Buffer, string |
|
callback |
callback |
function(err, res) {} |
Callback
name |
type |
description |
err |
Error() |
|
res |
object |
see |
Example
client.put("key", "value", function(err, res) {})
client.conditionalPut(key, value, ifValue, callback)
ConditionalPut sets the value
for a key
if the existing value matches the ifValue
.
Specifying an empty or null ifValue
means the entry must not yet exist.
Parameters
name |
type |
description |
key |
string |
|
value |
Buffer, string |
|
ifValue |
Buffer, string, null |
use null to put if entry doens't exists |
callback |
callback |
function(err, res) {} |
Callback
name |
type |
description |
err |
Error() |
|
actualValue |
Buffer |
If conditional put fails this value is set |
res |
object |
see |
Example
client.conditionalPut("status", "running", "stopped", function(err, actualValue, res) {})
client.conditionalPut("status", "new", null, function(err, actualValue, res) {})
client.contains(key, callback)
Contains determines if a key
exists in the datastore.
Parameters
name |
type |
description |
key |
string |
|
callback |
callback |
function(err, exists, res) {} |
Callback
name |
type |
description |
err |
Error() |
|
exists |
boolean |
|
res |
object |
see |
Example
client.contains("john", function(err, exists, res) {
if(exists === true) {
}
})
client.increment(key, increment, callback)
Increment increments the value at the specified key
by some increment
value.
Once called for a key
, Put & Get will return errors; only Increment will continue to be a valid command.
The value must be deleted before it can be reset using Put.
Parameters
name |
type |
description |
key |
string |
|
increment |
integer |
|
callback |
callback |
function(err, newValue, res) {} |
Callback
name |
type |
description |
err |
Error() |
|
newValue |
integer |
the new value for this counter, after the increment operation |
res |
object |
see |
Example
client.increment("counter", 5, function(err, newValue, res) {
console.log('counter current value is', newValue)
})
client.scan(start_key, end_key, limit, callback)
Scan the datastore for keys in the range of the start_key
and end_key
, limiting the result by limit
.
Parameters
name |
type |
description |
key |
string |
|
start_key |
string |
|
end_key |
string |
|
limit |
integer |
|
callback |
callback |
function(err, rows, res) {} |
Callback
name |
type |
description |
err |
Error() |
|
rows |
array |
|
res |
object |
see |
Example
client.scan("a", "Z", 100, function(err, rows, res) {
for(row as rows) {
console.log(row)
}
})
client.delete(key, callback)
Delete an entry from the datastore specified by key
.
Parameters
name |
type |
description |
key |
string |
|
callback |
callback |
function(err, res) {} |
Callback
name |
type |
description |
err |
Error() |
|
res |
object |
see |
Example
client.delete("key", function(err, res) {})
client.deleteRange(start_key, end_key, limit, callback)
Delete all keys found in a range, from start_key
to end_key
, limited by limit
.
Parameters
name |
type |
description |
key |
string |
|
start_key |
string |
|
end_key |
string |
|
limit |
integer |
|
callback |
callback |
function(err, deleted, res) {} |
Callback
name |
type |
description |
err |
Error() |
|
deleted |
integer |
number of entries deleted |
res |
object |
see |
Example
client.deleteRange("a", "Z", 100, function(err, deleted, res) {
console.log('deleted %d entries', deleted)
})
client.prepare()
Return you a new prepared client. It has all the methods from the original client.
Read Advanced client usage II to understand how to use this client.
You should always use this client when sending in multiple queries, this will batch them together in a single request.
Methods
method |
description |
flush |
Flush the prepared queries |
Example
var c = client.prepare()
c.get("key", function(err, value, res) {
})
c.get("key2", function(err, value, res) {
})
c.put("key3", "value", function(err, res) {
})
c.flush()
client.flush(callback)
Flush the prepared queries buffer, and send it as a batch request.
Parameters
name |
type |
description |
callback |
callback |
optional |
Callback
name |
type |
description |
err |
Error() |
batch request failed |
res |
object |
see |
Example
client.flush(function(err, res) {
if(err) {
}
else {
console.log('flushed %d queries.', res.responses.length)
}
})
Returns
Returns an response object.
property |
type |
description |
err |
Error() |
is null if no error was returned |
value |
string, number, boolean |
general response value |
res |
object |
see |
client.runTransaction(opts, transaction, callback)
RunTransaction executes a retryable transaction
function in
the context of a distributed transaction. The transaction is
automatically aborted if retryable function returns any error aside from
recoverable internal errors, and is automatically committed otherwise.
retryable should have no side effects which could cause problems in the event
it must be run more than once. The opts
contains transaction settings.
Parameters
name |
type |
description |
opts |
object |
options |
transacation |
retryable function |
function(txn, commit, abort) {} |
callback |
callback |
function(err, res) {} |
Transaction options
opt |
description |
default |
name |
transaction name for debugging |
"" |
isolation |
|
0 |
Callback
name |
type |
description |
err |
Error() |
if transaction fails |
res |
object |
see |
Extra
Response properties
The res
argument contains the full database response, each database command can
contain a different set of properties. This document will try to state some of the possible properties.
Properties
property |
type |
description |
timestamp |
integer |
timestamp of the returned entry |
wall_time |
integer |
timestamp of when the read or write operation was performed |
Transaction function
The transaction function is an retryable function, it may be
executed more than once. This function should never forget to
call commit
or abort
. Throwing an error inside this
function also aborts the transaction.
Arguments
name |
type |
description |
txn |
Prepared client |
this client is the same as client.prepare() , you can flush yourself if you don't wan't to commit yet. |
commit |
callback |
to try to commit transaction |
abort |
callback |
to abort transaction |
abort()
accepts an optional Error
. This error will be passed to the
.runTransaction callback.
Example
var transaction = function(txn, commit, abort) {
txn = txn.prepare()
for(var i = 0; i < 100; i++) {
var key = i.toString()
txn.put(key, "hello")
}
commit()
}
Compiling .proto files
Cockroachdb's protocol buffer files are mantained at a repository called cockroachdb/cockroach-proto, this is
maintained as a subtree
in this library, in case you need to manually update or change them, follow this steps.
If you want to sync them with the latest proto files
You will need to update the folder cockroach-proto with the latest content of the cockroachdb/cockroach-proto repository, you could do this with:
$ git subtree pull -P cockroach-proto [email protected]:cockroachdb/cockroach-proto.git master --squash
- Notice: I'm not sure if this is a good pattern, just be sure to update the folder contents.
Recompile the .proto files
Run the following npm script to compile the .proto files to javascript, it will automatically place the files in the lib folder.
$ npm run build-proto
Custom clock module
You may wan't to use a custom clock module in some cases, you can pass it through the clock
option, when instantiating a new Client
.
Your clock module should have a now
method, and this method should return the current timestamp in nanoseconds, here is an example:
var clockModule = module.exports = {
now: function TimestampNanoseconds() {
return ...;
}
}
var client = new Client({
clock: clockModule
})
Maintainers