kyoto-client
Version:
Client for Kyoto Tycoon
164 lines (139 loc) • 4.86 kB
text/coffeescript
http = require 'http'
querystring = require 'querystring'
csv = require 'csv'
util = require 'util'
assert = require 'assert'
RpcClient = require './rpc_client'
class Cursor
constructor: (@db) ->
# Cursors have their own client so that the cursor id can be the same
# for each one
@client = new RpcClient(@db.port, @db.host)
this
_jumpUsing: (procedure, args) ->
options = {}
switch args.length
when 1 then callback = args[0]
when 2
[key, callback] = args
when 3
[key, options, callback] = args
else
throw new Error("Invalid number of arguments (#{args.length}) to #{procedure}");
rpc_args = {CUR: 1}
rpc_args.key = key if key?
rpc_args.DB = options.database or @db.database
@client.call procedure, rpc_args, (error, status, output) ->
if error?
callback error, output
else if status == 200
callback undefined, output
else if status == 450
message = output.ERROR or "Cursor has been invalidated"
callback new Error(message), output
else if status == 501
callback new Error("#{procedure} is not supported by this database type"), output
else
callback new Error("Unexpected response from server: #{status}"), output
jump: (args...) ->
this._jumpUsing 'cur_jump', args
jumpBack: (args...) ->
this._jumpUsing 'cur_jump_back', args
_stepUsing: (procedure, callback) ->
rpc_args = {CUR: 1}
rpc_args.key = key if key?
@client.call procedure, rpc_args, (error, status, output) ->
if error?
callback error, output
else if status == 200
callback undefined, output
else if status == 450
callback new Error("Cursor has been invalidated"), output
else
callback new Error("Unexpected response from server: #{status}"), output
step: (callback) ->
this._stepUsing 'cur_step', callback
stepBack: (callback) ->
this._stepUsing 'cur_step_back', callback
setValue: (value, args...) ->
switch args.length
when 1 then callback = args[0]
when 2
step = args[0]
callback = args[1]
else
throw new Error("Invalid number of arguments (#{args.length}) to setValue");
rpc_args = {CUR: 1, value: value}
rpc_args.step = 1 if step?
@client.call 'cur_set_value', rpc_args, (error, status, output) ->
if error?
callback error, output
else if status == 200
callback undefined, output
else if status == 450
callback new Error("Cursor has been invalidated"), output
else
callback new Error("Unexpected response from server: #{status}"), output
# Remove the current cursor value
remove: (callback) ->
rpc_args = {CUR: 1}
@client.call 'cur_remove', rpc_args, (error, status, output) ->
if error?
callback error, output
else if status == 200
callback undefined, output
else if status == 450
callback new Error("Cursor has been invalidated"), output
else
callback new Error("Unexpected response from server: #{status}"), output
_getUsing: (procedure, args) ->
switch args.length
when 1 then callback = args[0]
when 2
step = args[0]
callback = args[1]
else
throw new Error("Invalid number of arguments (#{args.length}) to #{procedure}");
rpc_args = {CUR: 1}
rpc_args.step = 1 if step?
@client.call procedure, rpc_args, (error, status, output) ->
if error?
callback error, output
else if status == 200
callback undefined, output
else if status == 450
callback undefined, {}
else
callback new Error("Unexpected response from server: #{status}"), output
# All three of these functions accept a step argument that indicates whether to
# step or not. It seems 450 is returned when the cursor gets to the end
getKey: (args...) ->
this._getUsing 'cur_get_key', args
getValue: (args...) ->
this._getUsing 'cur_get_value', args
# Get current key and value of cursor
get: (args...) ->
this._getUsing 'cur_get', args
# Enumerate all entries of the cursor, calling the callback for each one
each: (callback) ->
process.nextTick =>
this.get true, (error, output) =>
if error
callback error, output
else
callback undefined, output
this.each(callback) if output.key?
delete: (callback) ->
request =
host: @db.host
port: @db.port
path: '/rpc/cur_delete?CUR=1'
headers:
'Connection': 'close'
assert.ok callback, "you must supply a callback"
http.get request, (response) =>
response.on 'end', =>
callback()
.on 'error', (error) ->
callback(error)
module.exports = Cursor