Skip to content

Repository files navigation

RoachJS - CockroachDB Driver

Note: RoachJS will only work against old versions of CockroachDB that expose the key-value API.

To interact with newer versions you can use a library that works with Postgres. For more, please see the CockroachDB docs.

NPM

Build Status

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

Initiating a client

varRoach=require('roachjs')varclient=newRoach({uri: 'https://localhost:8080'})module.exports=client

Basic client usage I

client.get("sample_key",function(err,value,res){if(err)throwerrclient.put("other_key",value,function(err,res){if(err){// Failed}else{// Sucess}})})

Advanced client usage I (Prepare & Flush)

// You should prepare your queries and send them in a single batch// For optimal performancevarc=client.prepare()// This callback will be the first to be executedc.get("sample_key",function(err,value,res){if(err)throwerr// Do something...})c.get("sample_key2",function(err,value,res){if(err)throwerr// Do something...})c.put("some_key","some_value",function(err){if(err)throwerr// Do something})// The flush callback is the last one to be calledc.flush(function(err,res){if(err)throwerrconsole.log('Sucessfuly flushed %d queries.',res.responses.length)})

Advanced client usage II (Transactions)

varopts={name: "transaction example",}varerrNoApples=newError('Insufficient apples!')vartransaction=function(txn,commit,abort){txn.get("applesInStock",function(err,value,res){if(err||applesInStock.err){returnabort(err)}vardispatch=5varinStock=parseInt(applesInStock.value)if(inStock<dispatch){returnabort(errNoApples)}// Upgrade for a prepared clienttxn=txn.prepare()txn.increment("applesInStock",-dispatch)txn.increment("applesInRoute",+dispatch)// Commit automatically flushescommit()})}client.runTransaction(opts,transaction,function(err,res){if(err===errNoApples){// Alert user there are no more apples...}elseif(err){// Transaction failed...}else{// Transaction commited...}})

Interface

new Client(opts)

Returns a new roachjs client with options.

Parameters
nametypedescription
optsobjectsee
Client options
optdescriptiondefault
uriuri to the cockroach http endpointhttps://localhost:8080/
hosthost or ip to the cockroach http endpointlocalhost
portport to the cockroach http endpoint8080
sslconnect throught httpstrue
useruser to run the requests withroot
retryretry requests when cockroach responds with a busy signaltrue
httphttp module to userequire('https')
agenthttp agent to use on the requests (read more)new http.Agent()
clockclock module to use (read more)internal clock module
Methods
method
get
put
conditionalPut
contains
increment
scan
delete
deleteRange
prepare
runTransaction

client.get(key, callback)

Gets a single entry from the datastore, specified by key.

Parameters
nametypedescription
keystring
callbackcallbackfunction(err, value, res) {}
Callback
nametypedescription
errError()
valueBuffer
resobjectsee
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
nametypedescription
keystring
valueBuffer, string
callbackcallbackfunction(err, res) {}
Callback
nametypedescription
errError()
resobjectsee
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
nametypedescription
keystring
valueBuffer, string
ifValueBuffer, string, nulluse null to put if entry doens't exists
callbackcallbackfunction(err, res) {}
Callback
nametypedescription
errError()
actualValueBufferIf conditional put fails this value is set
resobjectsee
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
nametypedescription
keystring
callbackcallbackfunction(err, exists, res) {}
Callback
nametypedescription
errError()
existsboolean
resobjectsee
Example
client.contains("john",function(err,exists,res){if(exists===true){// john exists in the datastore}})

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
nametypedescription
keystring
incrementinteger
callbackcallbackfunction(err, newValue, res) {}
Callback
nametypedescription
errError()
newValueintegerthe new value for this counter, after the increment operation
resobjectsee
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
nametypedescription
keystring
start_keystring
end_keystring
limitinteger
callbackcallbackfunction(err, rows, res) {}
Callback
nametypedescription
errError()
rowsarray
resobjectsee
Example
client.scan("a","Z",100,function(err,rows,res){for(rowasrows){console.log(row)}})

client.delete(key, callback)

Delete an entry from the datastore specified by key.

Parameters
nametypedescription
keystring
callbackcallbackfunction(err, res) {}
Callback
nametypedescription
errError()
resobjectsee
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
nametypedescription
keystring
start_keystring
end_keystring
limitinteger
callbackcallbackfunction(err, deleted, res) {}
Callback
nametypedescription
errError()
deletedintegernumber of entries deleted
resobjectsee
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
methoddescription
flushFlush the prepared queries
Example
varc=client.prepare()c.get("key",function(err,value,res){// Do something...})c.get("key2",function(err,value,res){// Do something...})c.put("key3","value",function(err,res){// Do something...})c.flush()

client.flush(callback)

Flush the prepared queries buffer, and send it as a batch request.

Parameters
nametypedescription
callbackcallbackoptional
Callback
nametypedescription
errError()batch request failed
resobjectsee
Example
client.flush(function(err,res){if(err){// Flush failed..}else{console.log('flushed %d queries.',res.responses.length)}})
Returns

Returns an response object.

propertytypedescription
errError()is null if no error was returned
valuestring, number, booleangeneral response value
resobjectsee

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
nametypedescription
optsobjectoptions
transacationretryable functionfunction(txn, commit, abort) {}
callbackcallbackfunction(err, res) {}
Transaction options
optdescriptiondefault
nametransaction name for debugging""
isolation0
Callback
nametypedescription
errError()if transaction fails
resobjectsee

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
propertytypedescription
timestampintegertimestamp of the returned entry
wall_timeintegertimestamp 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
nametypedescription
txnPrepared clientthis client is the same as client.prepare(), you can flush yourself if you don't wan't to commit yet.
commitcallbackto try to commit transaction
abortcallbackto abort transaction
  • abort() accepts an optional Error. This error will be passed to the .runTransaction callback.
Example
vartransaction=function(txn,commit,abort){txn=txn.prepare()for(vari=0;i<100;i++){varkey=i.toString()txn.put(key,"hello")}// Commit automatically flushes// the prepared transaction.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 git@github.com: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:

varclockModule=module.exports={now: functionTimestampNanoseconds(){// Should return the current timestamp in nanosecondsreturn ...;}}varclient=newClient({clock: clockModule})

Maintainers

About

Node.js driver for cockroachdb.

Resources

Stars

14 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages