11.9. Hot Rod Node.js Client
Promise
instances, allowing the client to easily chain multiple invocations together and centralizing error handling.
11.9.1. Installing the Hot Rod Node.js Client
Procedure 11.3. Installing the Hot Rod Node.js Client
- Download the
jboss-datagrid-<version>-nodejs-client.zip
from the Red Hat Customer Portal. - Extract the downloaded archive.
- Use
npm
to install the provided tarball, as seen in the following command:npm install /path/to/jboss-datagrid-7.0.0-nodejs-client/infinispan-0.2.0.Final-redhat-1.tgz
11.9.2. Hot Rod Node.js Requirements
- Node.js version 0.10 or higher.
- JBoss Data Grid server instance 7.0.0 or higher.
11.9.3. Hot Rod Node.js Basic Functionality
localhost:11222
:
var infinispan = require('infinispan'); // Obtain a connection to the JBoss Data Grid server // As no cache is specified all operations will occur on the 'default' cache var connected = infinispan.client({port: 11222, host: '127.0.0.1'}); connected.then(function (client) { // Attempt to put a value in the cache. var clientPut = client.put('key', 'value'); // Retrieve the value just placed var clientGet = clientPut.then( function() { return client.get('key'); }); // Print out the value that was retrieved var showGet = clientGet.then( function(value) { console.log('get(key)=' + value); }); // Disconnect from the server return showGet.finally( function() { return client.disconnect(); }); }).catch(function(error) { // Log any errors received console.log("Got error: " + error.message); });
To connect to a specific cache the cacheName
attribute may be defined when specifying the location of the JBoss Data Grid server instance, as seen in the following example:
var infinispan = require('infinispan'); // Obtain a connection to the JBoss Data Grid server // and connect to namedCache var connected = infinispan.client( {port: 11222, host: '127.0.0.1'}, {cacheName: 'namedCache'}); connected.then(function (client) { // Log the result of the connection console.log('Connected to `namedCache`'); // Disconnect from the server return client.disconnect(); }).catch(function(error) { // Log any errors received console.log("Got error: " + error.message); });
In addition to placing single entries the putAll
and getAll
methods may be used to place or retrieve a set of data. The following example walks through these operations:
var infinispan = require('infinispan'); // Obtain a connection to the JBoss Data Grid server // As no cache is specified all operations will occur on the 'default' cache var connected = infinispan.client({port: 11222, host: '127.0.0.1'}); connected.then(function (client) { var data = [ {key: 'multi1', value: 'v1'}, {key: 'multi2', value: 'v2'}, {key: 'multi3', value: 'v3'}]; // Place all of the key/value pairs in the cache var clientPutAll = client.putAll(data); // Obtain the values for two of the keys var clientGetAll = clientPutAll.then( function() { return client.getAll(['multi2', 'multi3']); }); // Print out the values obtained. var showGetAll = clientGetAll.then( function(entries) { console.log('getAll(multi2, multi3)=%s', JSON.stringify(entries)); } ); // Obtain an iterator for the cache var clientIterator = showGetAll.then( function() { return client.iterator(1); }); // Iterate over the entries in the cache, printing the values var showIterated = clientIterator.then( function(it) { function loop(promise, fn) { // Simple recursive loop over iterator's next() call return promise.then(fn).then(function (entry) { return !entry.done ? loop(it.next(), fn) : entry.value; }); } return loop(it.next(), function (entry) { console.log('iterator.next()=' + JSON.stringify(entry)); return entry; }); } ); // Clear the cache of all values var clientClear = showIterated.then( function() { return client.clear(); }); // Disconnect from the server return clientClear.finally( function() { return client.disconnect(); }); }).catch(function(error) { // Log any errors received console.log("Got error: " + error.message); });
11.9.4. Hot Rod Node.js Conditional Operations
getWithMetadata
will retrieve the value and any associated metadata with the key.
var infinispan = require('infinispan'); // Obtain a connection to the JBoss Data Grid server // As no cache is specified all operations will occur on the 'default' cache var connected = infinispan.client({port: 11222, host: '127.0.0.1'}); connected.then(function (client) { // Attempt to put a value in the cache if it does not exist var clientPut = client.putIfAbsent('cond', 'v0'); // Print out the result of the put operation var showPut = clientPut.then( function(success) { console.log(':putIfAbsent(cond)=' + success); }); // Replace the value in the cache var clientReplace = showPut.then( function() { return client.replace('cond', 'v1'); } ); // Print out the result of the replace var showReplace = clientReplace.then( function(success) { console.log('replace(cond)=' + success); }); // Obtain the value and metadata var clientGetMetaForReplace = showReplace.then( function() { return client.getWithMetadata('cond'); }); // Replace the value only if the version matches var clientReplaceWithVersion = clientGetMetaForReplace.then( function(entry) { console.log('getWithMetadata(cond)=' + JSON.stringify(entry)); return client.replaceWithVersion('cond', 'v2', entry.version); } ); // Print out the result of the previous replace var showReplaceWithVersion = clientReplaceWithVersion.then( function(success) { console.log('replaceWithVersion(cond)=' + success); }); // Obtain the value and metadata var clientGetMetaForRemove = showReplaceWithVersion.then( function() { return client.getWithMetadata('cond'); }); // Remove the value only if the version matches var clientRemoveWithVersion = clientGetMetaForRemove.then( function(entry) { console.log('getWithMetadata(cond)=' + JSON.stringify(entry)); return client.removeWithVersion('cond', entry.version); } ); // Print out the result of the previous remove var showRemoveWithVersion = clientRemoveWithVersion.then( function(success) { console.log('removeWithVersion(cond)=' + success)}); // Disconnect from the server return showRemoveWithVersion.finally( function() { return client.disconnect(); }); }).catch(function(error) { // Log any errors received console.log("Got error: " + error.message); });
11.9.5. Hot Rod Node.js Data Sets
var infinispan = require('infinispan'); // Accepts multiple addresses and fails over if connection not possible var connected = infinispan.client( [{port: 99999, host: '127.0.0.1'}, {port: 11222, host: '127.0.0.1'}]); connected.then(function (client) { // Obtain a list of all members in the cluster var members = client.getTopologyInfo().getMembers(); // Print out the list of members console.log('Connected to: ' + JSON.stringify(members)); // Disconnect from the server return client.disconnect(); }).catch(function(error) { // Log any errors received console.log("Got error: " + error.message); });
11.9.6. Hot Rod Node.js Remote Events
addListener
method. This method takes the event type (create
, modify
, remove
, or expiry
) and the function callback as parameter. For more information on Remote Event Listeners refer to Section 8.5, “Remote Event Listeners (Hot Rod)”. An example of this is shown below:
var infinispan = require('infinispan'); var Promise = require('promise'); var connected = infinispan.client({port: 11222, host: '127.0.0.1'}); connected.then(function (client) { var clientAddListenerCreate = client.addListener( 'create', function(key) { console.log('[Event] Created key: ' + key); }); var clientAddListeners = clientAddListenerCreate.then( function(listenerId) { // Multiple callbacks can be associated with a single client-side listener. // This is achieved by registering listeners with the same listener id // as shown in the example below. var clientAddListenerModify = client.addListener( 'modify', function(key) { console.log('[Event] Modified key: ' + key); }, {listenerId: listenerId}); var clientAddListenerRemove = client.addListener( 'remove', function(key) { console.log('[Event] Removed key: ' + key); }, {listenerId: listenerId}); return Promise.all([clientAddListenerModify, clientAddListenerRemove]); }); var clientCreate = clientAddListeners.then( function() { return client.putIfAbsent('eventful', 'v0'); }); var clientModify = clientCreate.then( function() { return client.replace('eventful', 'v1'); }); var clientRemove = clientModify.then( function() { return client.remove('eventful'); }); var clientRemoveListener = Promise.all([clientAddListenerCreate, clientRemove]).then( function(values) { var listenerId = values[0]; return client.removeListener(listenerId); }); return clientRemoveListener.finally( function() { return client.disconnect(); }); }).catch(function(error) { console.log("Got error: " + error.message); });
11.9.7. Hot Rod Node.js Working with Clusters
- The client only needs to know about a single server's address to receive information about the entire server cluster, regardless of the cluster size.
- For distributed caches, key-based operations are routed in the cluster using the same consistent hash algorithms used by the server. This means that the client can locate where any particular key resides without the need for extra network hops.
- For distributed caches, multi-key or key-less operations routed in round-robin fashion.
- For replicated and invalidated caches, all operations are routed in round-robin fashion, regardless of whether they are key-based or multi-key/key-less.
var infinispan = require('infinispan'); var connected = infinispan.client({port: 11322, host: '127.0.0.1'}); connected.then(function (client) { var members = client.getTopologyInfo().getMembers(); // Should show all expected cluster members console.log('Connected to: ' + JSON.stringify(members)); // Add your own operations here... return client.disconnect(); }).catch(function(error) { // Log any errors received console.log("Got error: " + error.message); });