このコンテンツは選択した言語では利用できません。
11.9. Hot Rod Node.js Client
The Hot Rod Node.js client is an asynchronous event-driven client allowing Node.js users to communicate to JBoss Data Grid servers. This client supports many of the features in the Java client, including the ability to execute and store scripts, utilize cache listeners, and receive the full cluster topology.
The asynchronous operation results are represented with
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
The Hot Rod Node.js client is included in a separate distribution, and must be downloaded independently of JBoss Data Grid. Follow the below instructions to install this 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
In order to use the Hot Rod Node.js the following prerequisites must be met:
- 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
The following example shows how to connect to a JBoss Data Grid server and perform basic operations, such as putting and retrieving data. The following example assumes that a JBoss Data Grid server is available at the default location of
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); });
Connecting to a Named Cache
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); });
Using Data Sets
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
The Hot Rod protocol stores metadata in addition to each value associated with the keys. The
getWithMetadata
will retrieve the value and any associated metadata with the key.
The following example demonstrates utilizing this metadata:
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
The client may specify multiple server addresses when a connection is defined. When multiple servers are defined it will loop through each one until a successful connection to a node is obtained. An example of this configuration is below:
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
The Hot Rod Node.js client supports remote cache listeners, and these may be added using the
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
JBoss Data Grid server instances may be clustered together to provide failover and capabilities for scaling up. While working with a cluster is very similar to using a single instance there are a few considerations:
- 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.
All routing and failover is transparent to the client, so operations executed against a cluster look identical to the code examples performed above.
The cluster topology can be obtained using the following example:
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); });