UNPKG

dl

Version:

DreamLab Libs

493 lines (428 loc) 14.2 kB
/*jslint node: true */ 'use strict'; var Long = require('long'); var OpalClient = require('../opal/OpalClient.js').OpalClient; var Errors = require('./Errors.js'); var Nosqldb = function(datasource, timeout) { if (timeout && timeout > 1) { timeout = 1 } this._datasource = datasource; var rpcUrl = this._getRpcUrl(datasource); this._nosqldbRpc = new OpalClient(rpcUrl, [ 'get_metadata', 'insert', 'multi_insert', 'update', 'get', 'multi_get', 'get_range', 'remove', 'batch' ], timeout); this._metadata = null; this._timerId = setInterval(this._refreshMetadata.bind(this), 60 * 1000); }; Nosqldb.prototype._getRpcUrl = function(datasource) { var keyspace = datasource.split('.')[0]; return keyspace + '.nosqldb.onetapi.pl'; }; Nosqldb.prototype._getMetadata = function(refresh, callback) { if (this._metadata && !refresh && callback) { return callback(null, this._metadata); } console.log('Getting metadata'); var that = this; this._nosqldbRpc.get_metadata([], function(err, res) { if (err) { console.error('Error while getting metadata: %s', err); if (callback) { return callback(err); } } that._metadata = res; if (callback) { callback(null, that._metadata); } }); }; Nosqldb.prototype._refreshMetadata = function() { this._getMetadata(true); } Nosqldb.prototype._encodeValue = function(value, typestring) { if (value === null) { return value; } var m = typestring.match(/(\w+)<([\w, ]+)>/); if (typestring === 'timestamp') { return value.getTime(); } else if (typestring === 'bigint' || typestring === 'counter' || typestring === 'decimal') { return value.toString(); } else if (typestring === 'blob') { return value.toString('hex'); } else if (m) { var collection = m[1]; var t = m[2]; var that = this; if (collection === 'set' || collection === 'list') { return value.map(function(v) { return that._encodeValue(v, t); }); } else if (collection === 'map') { var tSplit = t.split(', '); var tK = tSplit[0]; var tV = tSplit[1]; var encodedMap = []; for (var k in value) { encodedMap.push([that._encodeValue(k, tK), that._encodeValue(value[k], tV)]); } return encodedMap; } } return value; }; Nosqldb.prototype._decodeValue = function(value, typestring) { if (value === null) { return value; } var m = typestring.match(/(\w+)<([\w, ]+)>/); if (typestring === 'timestamp') { return new Date(value); } else if (typestring === 'bigint' || typestring === 'counter') { return Long.fromString(value, false); } else if (typestring === 'decimal') { return parseFloat(value); } else if (typestring === 'blob') { return new Buffer(value, 'hex'); } else if (m) { var collection = m[1]; var t = m[2]; var that = this; if (collection === 'set' || collection === 'list') { return value.map(function(v) { return that._decodeValue(v, t); }); } else if (collection === 'map') { var tSplit = t.split(', '); var tK = tSplit[0]; var tV = tSplit[1]; var decodedMap = {}; value.forEach(function(item) { decodedMap[that._decodeValue(item[0], tK)] = that._decodeValue(item[1], tV); }); return decodedMap; } } return value; }; Nosqldb.prototype._encodeKey = function(table, key) { if (!(key instanceof Array)) { key = [key]; } var tableMetadata = this._metadata.tables[table]; var encodedKey = []; for (var i = 0; i < key.length; i++) { var typestring = tableMetadata.primary_key[i]['typestring']; encodedKey[i] = this._encodeValue(key[i], typestring); } return encodedKey; }; Nosqldb.prototype._encodeColumns = function(table, columns) { var tableMetadata = this._metadata.tables[table]; var encodedColumns = {}; for (var name in columns) { var typestring = tableMetadata.columns[name]['typestring']; encodedColumns[name] = this._encodeValue(columns[name], typestring); } return encodedColumns; }; Nosqldb.prototype._encodeAssignments = function(table, assignments) { var tableMetadata = this._metadata.tables[table]; var encodedAssignments = {}; for (var name in assignments) { var typestring = tableMetadata.columns[name]['typestring']; var operator = assignments[name][0]; var value = assignments[name][1]; var m = typestring.match(/(\w+)<([\w, ]+)>/); if ((operator instanceof Array) && operator.length === 1 && m) { var collection = m[1]; var t = m[2]; if (collection === 'list') { value = this._encodeValue(value, t); } else if (collection === 'map') { var tSplit = t.split(', '); var tK = tSplit[0]; var tV = tSplit[1]; operator = [this._encodeValue(operator[0], tK)]; value = this._encodeValue(value, tV); } } else { value = this._encodeValue(value, typestring); } encodedAssignments[name] = [operator, value]; } return encodedAssignments; }; Nosqldb.prototype._handleError = function(err) { switch(err.code) { case Errors.INVALID_REQUEST: return new Errors.InvalidRequest(err.message); case Errors.REQUEST_ERROR: return new Errors.RequestError(err.message); case Errors.CONSISTENCY_ERROR: return new Errors.ConsistencyError(err.message); case Errors.CLUSTER_ERROR: return new Errors.ClusterError(err.message); case Errors.CONNECTION_ERROR: return new Errors.ConnectionError(err.message); default: return err; } }; Nosqldb.prototype._decodeRow = function(table, row) { var tableMetadata = this._metadata.tables[table]; for (var name in row) { var typestring = tableMetadata.columns[name]['typestring']; row[name] = this._decodeValue(row[name], typestring); } return row; }; Nosqldb.prototype._handleResult = function(table, res) { if (!res) { return res; } var that = this; if (res instanceof Array) { return res.map(function decodeRow(row) { return that._decodeRow(table, row); }); } return this._decodeRow(table, res); }; Nosqldb.prototype.insert = function(table, key, columns, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } var ttl = options.ttl || null; var consistency = options.consistency || 'default'; var that = this; this._getMetadata(false, function(err) { if (err) { return callback(err); } key = that._encodeKey(table, key); columns = that._encodeColumns(table, columns); that._nosqldbRpc.insert([table, key, columns, ttl, consistency], function(err, res) { if (err) { return callback(that._handleError(err)); } callback(null, null); }); }); }; Nosqldb.prototype.multiInsert = function(items, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } var consistency = options.consistency || 'default'; var that = this; this._getMetadata(false, function(err) { if (err) { return callback(err); } var encodedItems = items.map(function(item) { return { table: item.table, key: that._encodeKey(item.table, item.key), columns: that._encodeColumns(item.table, item.columns), ttl: item.ttl }; }); that._nosqldbRpc.multi_insert([encodedItems, consistency], function(err, res) { if (err) { return callback(that._handleError(err)); } callback(null, null); }); }); }; Nosqldb.prototype.update = function(table, key, assignments, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } var ttl = options.ttl || null; var consistency = options.consistency || 'default'; var that = this; this._getMetadata(false, function(err) { if (err) { return callback(err); } key = that._encodeKey(table, key); assignments = that._encodeAssignments(table, assignments); that._nosqldbRpc.update([table, key, assignments, ttl, consistency], function(err, res) { if (err) { return callback(that._handleError(err)); } callback(null, null); }); }); }; Nosqldb.prototype.get = function(table, key, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } var columns = options.columns || null; var consistency = options.consistency || 'default'; var that = this; this._getMetadata(false, function(err) { if (err) { return callback(err); } key = that._encodeKey(table, key); that._nosqldbRpc.get([table, key, columns, consistency], function(err, res) { if (err) { return callback(that._handleError(err)); } callback(null, that._handleResult(table, res)); }); }); }; Nosqldb.prototype.multiGet = function(items, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } var consistency = options.consistency || 'default'; var that = this; this._getMetadata(false, function(err) { if (err) { return callback(err); } var encodedItems = items.map(function(item) { return { table: item.table, key: that._encodeKey(item.table, item.key), columns: item.columns }; }); that._nosqldbRpc.multi_get([encodedItems, consistency], function(err, res) { if (err) { return callback(that._handleError(err)); } var results = res.map(function(result, i) { return that._handleResult(items[i].table, result); }); callback(null, results); }); }); }; Nosqldb.prototype.getRange = function(table, keyPrefix, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } var rangeLt = options.rangeLt || null; var rangeLte = options.rangeLte || null; var rangeGt = options.rangeGt || null; var rangeGte = options.rangeGte || null; var columns = options.columns || null; var orderBy = options.orderBy || null; var limit = options.limit || null; var consistency = options.consistency || 'default'; var that = this; this._getMetadata(false, function(err) { if (err) { return callback(err); } keyPrefix = that._encodeKey(table, keyPrefix); that._nosqldbRpc.get_range([ table, keyPrefix, rangeLt, rangeLte, rangeGt, rangeGte, columns, orderBy, limit, consistency ], function(err, res) { if (err) { return callback(that._handleError(err)); } callback(null, that._handleResult(table, res)); }); }); }; Nosqldb.prototype.remove = function(table, key, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } var columns = options.columns || null; var consistency = options.consistency || 'default'; var that = this; this._getMetadata(false, function(err) { if (err) { return callback(err); } key = that._encodeKey(table, key); that._nosqldbRpc.remove([table, key, columns, consistency], function(err, res) { if (err) { return callback(that._handleError(err)); } callback(null, null); }); }); }; Nosqldb.prototype.batch = function(batch, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } var consistency = options.consistency || 'default'; var that = this; var operations = []; this._getMetadata(false, function(err) { if (err) { return callback(err); } batch.operations.forEach(function(operation) { var name = operation.name; var params = operation.params; if (name === 'insert') { operations.push(['insert', [ params.table, that._encodeKey(params.table, params.key), that._encodeColumns(params.table, params.columns), params.ttl ]]); } else if (name === 'remove') { operations.push(['remove', [ params.table, that._encodeKey(params.table, params.key), params.columns ]]); } }); that._nosqldbRpc.batch([operations, consistency], function(err, res) { if (err) { return callback(that._handleError(err)); } callback(null, null); }); }); }; Nosqldb.prototype.destroy = function() { clearInterval(this._timerId); }; exports.Nosqldb = Nosqldb;