infinispan 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/Jenkinsfile-release +1 -1
  2. package/README.md +31 -907
  3. package/documentation/asciidoc/stories/assembly_client_usage_examples.adoc +10 -0
  4. package/documentation/asciidoc/stories/assembly_installation_configuration.adoc +20 -0
  5. package/documentation/asciidoc/titles/js_client.asciidoc +28 -0
  6. package/documentation/asciidoc/titles/stories.adoc +5 -0
  7. package/documentation/asciidoc/topics/attributes/community-attributes.adoc +8 -0
  8. package/documentation/asciidoc/topics/attributes/downstream-attributes.adoc +2 -0
  9. package/documentation/asciidoc/topics/code_examples/authentication-digest.js +12 -0
  10. package/documentation/asciidoc/topics/code_examples/authentication-external.js +15 -0
  11. package/documentation/asciidoc/topics/code_examples/authentication-oauthbearer.js +10 -0
  12. package/documentation/asciidoc/topics/code_examples/authentication-plain.js +11 -0
  13. package/documentation/asciidoc/topics/code_examples/authentication-scram.js +11 -0
  14. package/documentation/asciidoc/topics/code_examples/await-multiple-entries.js +36 -0
  15. package/documentation/asciidoc/topics/code_examples/await-single-entries.js +29 -0
  16. package/documentation/asciidoc/topics/code_examples/conditional-operations.js +57 -0
  17. package/documentation/asciidoc/topics/code_examples/connection-multiple-servers.js +23 -0
  18. package/documentation/asciidoc/topics/code_examples/connection-xsite-cluster-switch.js +39 -0
  19. package/documentation/asciidoc/topics/code_examples/connection-xsite.js +13 -0
  20. package/documentation/asciidoc/topics/code_examples/data-types.js +30 -0
  21. package/documentation/asciidoc/topics/code_examples/encryption-crypto-store.js +11 -0
  22. package/documentation/asciidoc/topics/code_examples/encryption-private-key.js +13 -0
  23. package/documentation/asciidoc/topics/code_examples/encryption-sni-hostname.js +9 -0
  24. package/documentation/asciidoc/topics/code_examples/encryption-trust-certs.js +8 -0
  25. package/documentation/asciidoc/topics/code_examples/ephemeral-data.js +52 -0
  26. package/documentation/asciidoc/topics/code_examples/hello-world.js +42 -0
  27. package/documentation/asciidoc/topics/code_examples/key-value-converter.js +67 -0
  28. package/documentation/asciidoc/topics/code_examples/logging-configuration.js +2 -0
  29. package/documentation/asciidoc/topics/code_examples/multiple-entries.js +64 -0
  30. package/documentation/asciidoc/topics/code_examples/register-event-listener.js +64 -0
  31. package/documentation/asciidoc/topics/code_examples/sample-script-execute.js +33 -0
  32. package/documentation/asciidoc/topics/code_examples/sample-script.js +3 -0
  33. package/documentation/asciidoc/topics/code_examples/single-entries.js +49 -0
  34. package/documentation/asciidoc/topics/config_examples/logging.json +14 -0
  35. package/documentation/asciidoc/topics/proc_configuring_authentication.adoc +16 -0
  36. package/documentation/asciidoc/topics/proc_configuring_connections.adoc +25 -0
  37. package/documentation/asciidoc/topics/proc_configuring_connections_xsite.adoc +18 -0
  38. package/documentation/asciidoc/topics/proc_configuring_data_formats.adoc +30 -0
  39. package/documentation/asciidoc/topics/proc_configuring_encryption.adoc +15 -0
  40. package/documentation/asciidoc/topics/proc_configuring_logging.adoc +28 -0
  41. package/documentation/asciidoc/topics/proc_installing_clients.adoc +58 -0
  42. package/documentation/asciidoc/topics/proc_switching_clusters.adoc +17 -0
  43. package/documentation/asciidoc/topics/ref_authentication_mechanisms.adoc +68 -0
  44. package/documentation/asciidoc/topics/ref_client_usage.adoc +116 -0
  45. package/documentation/asciidoc/topics/ref_encryption.adoc +71 -0
  46. package/lib/codec.js +153 -2
  47. package/lib/infinispan.js +33 -1
  48. package/lib/io.js +23 -16
  49. package/lib/protocols.js +165 -68
  50. package/lib/protostream/message-wrapping.proto +134 -0
  51. package/lib/protostream/query.proto +122 -0
  52. package/lib/sasl/bitops.js +24 -0
  53. package/lib/sasl/digest.js +188 -0
  54. package/lib/sasl/external.js +54 -0
  55. package/lib/sasl/factory.js +71 -0
  56. package/lib/sasl/oauthbearer.js +63 -0
  57. package/lib/sasl/plain.js +65 -0
  58. package/lib/sasl/scram.js +135 -0
  59. package/lib/utils.js +1 -1
  60. package/memory-profiling/helper.js +9 -0
  61. package/memory-profiling/infinispan_memory_many_get.js +1 -3
  62. package/memory-profiling/infinispan_memory_one_get.js +6 -4
  63. package/package.json +7 -13
  64. package/run-servers.sh +17 -8
  65. package/run-testsuite.sh +1 -1
  66. package/smoke-tests.sh +8 -2
  67. package/spec/codec_spec.js +7 -7
  68. package/spec/configs/infinispan-clustered.xml +17 -14
  69. package/spec/configs/infinispan-ssl.xml +25 -22
  70. package/spec/configs/infinispan-xsite-EARTH.xml +17 -14
  71. package/spec/configs/infinispan-xsite-MOON.xml +14 -11
  72. package/spec/configs/infinispan.xml +22 -13
  73. package/spec/infinispan_auth_spec.js +16 -37
  74. package/spec/protostream_spec.js +237 -0
  75. package/spec/utils/testing.js +1 -3
  76. package/lib/bitops.js +0 -26
  77. package/lib/scram.js +0 -116
package/lib/codec.js CHANGED
@@ -6,6 +6,9 @@
6
6
  , INT = Math.pow(2, 31);
7
7
 
8
8
  var _ = require('underscore');
9
+ var protobuf = require('protobufjs');
10
+ var path = require('path');
11
+
9
12
  var f = require('./functional');
10
13
  var utils = require('./utils');
11
14
 
@@ -16,8 +19,11 @@
16
19
  exports.encodeVLong = f.lift(doEncodeVLong, _.identity);
17
20
  exports.encodeJSON = f.lift(doEncodeJSON, _.identity);
18
21
  exports.encodeBytes = f.lift(doEncodeBytes, _.identity);
22
+ exports.encodeBytesWithLength = f.lift(doEncodeBytesWithLength, _.identity);
19
23
  exports.encodeString = f.lift(doEncodeString, _.identity);
20
24
  exports.encodeSignedInt = f.lift(doEncodeSignedInt, _.identity);
25
+ exports.encodeProtobuf = f.lift(doEncodeProtobuf, _.identity);
26
+ exports.encodeQuery = f.lift(doEncodeQuery,_.identity);
21
27
 
22
28
  exports.decodeUByte = f.lift(doDecodeUByte, _.identity);
23
29
  exports.decodeVInt = f.lift(doDecodeVInt, _.identity);
@@ -29,6 +35,8 @@
29
35
  exports.decodeSignedInt = f.lift(doDecodeSignedInt, _.identity);
30
36
  exports.decodeVariableBytes = f.lift(doDecodeVariableBytes, _.identity);
31
37
  exports.decodeShort = f.lift(doDecodeShort, _.identity);
38
+ exports.decodeProtobuf = f.lift(doDecodeProtobuf, _.identity);
39
+ exports.decodeQuery = f.lift(doDecodeQuery,_.identity);
32
40
 
33
41
  exports.lastDecoded = function(values) {
34
42
  return values[0];
@@ -79,10 +87,54 @@
79
87
  return _.compose(updateEncOffset(bytebuf), checkedWriteBytes(bytebuf))(bytes);
80
88
  }
81
89
 
90
+ function doEncodeBytesWithLength(bytebuf, bytes) {
91
+ return _.compose(updateEncOffset(bytebuf), checkedWriteBytesWithLength(bytebuf))(bytes);
92
+ }
93
+
82
94
  function doEncodeSignedInt(bytebuf, num) {
83
95
  return _.compose(updateEncOffset(bytebuf), checkedWriteSignedInt(bytebuf), zigZag)(num);
84
96
  }
85
97
 
98
+ function doEncodeProtobuf(bytebuf, message, typeId) {
99
+ return doEncodeBytesWithLength(bytebuf,encodeProtobuf(message,typeId));
100
+ }
101
+
102
+ function encodeProtobufInstance(root){
103
+ return function(obj){
104
+ return root.encode(obj).finish();
105
+ }
106
+ }
107
+
108
+ function encodeProtobuf(message,typeId){
109
+ return _.compose(encodeProtobufInstance(WrappedMessage), createWrappedMessage)(message,typeId);
110
+ }
111
+
112
+ function doEncodeQuery(bytebuf,query){
113
+ return doEncodeBytesWithLength(bytebuf,encodeProtobufInstance(Query.QueryRequest)(query));
114
+ }
115
+
116
+ function createWrappedMessage(message,typeId){
117
+ var wrappedMessage={};
118
+ if(_.isNumber(message)){
119
+ return f.merge(wrappedMessage,{'wrappedDouble':message});
120
+ }
121
+ if(_.isString(message)){
122
+ return f.merge(wrappedMessage,{'wrappedString':message});
123
+ }
124
+ if(_.isBoolean(message)){
125
+ return f.merge(wrappedMessage,{'wrappedBool':message});
126
+ }
127
+ if(_.isArrayBuffer(message)){
128
+ return f.merge(wrappedMessage,{'wrappedBytes':message});
129
+ }
130
+ if(f.existy(message.$type)){
131
+ var encodedMessage = encodeProtobufInstance(message.$type)(message);
132
+ var messageTypeId = typeId(message.$type.fullName);
133
+ return f.merge(wrappedMessage,{'wrappedMessage':encodedMessage},{'wrappedTypeId':messageTypeId});
134
+ }
135
+ throw new Error("Provide valid data types.");
136
+ }
137
+
86
138
  function zigZag(num) {
87
139
  return (num << 1) ^ (num >> 31);
88
140
  }
@@ -90,8 +142,8 @@
90
142
  var nullCheck = f.validator('must not be null', f.existy);
91
143
  var number = f.validator('must be a number', _.isNumber);
92
144
  var positiveOrZero = f.validator('must be >= 0', f.greaterThan(-1));
93
- var intTooBig = f.validator('must be less than 2^31', f.lessThan(Math.pow(2, 31)));
94
- var shortTooBig = f.validator('must be less than 2^15', f.lessThan(Math.pow(2, 15)));
145
+ var intTooBig = f.validator('must be less than 2^32', f.lessThan(Math.pow(2, 32)));
146
+ var shortTooBig = f.validator('must be less than 2^16', f.lessThan(Math.pow(2, 16)));
95
147
  var longTooBig = f.validator('must be less than 2^53 (javascript safe integer limitation)',
96
148
  f.lessThan(Math.pow(2, 53)));
97
149
  var stringOrNullCheck = f.validator('must be a String or null', stringOrNull);
@@ -124,6 +176,10 @@
124
176
  return f.partial1(f.condition1(nullCheck), uncheckedWriteBytes(bytebuf));
125
177
  }
126
178
 
179
+ function checkedWriteBytesWithLength(bytebuf) {
180
+ return f.partial1(f.condition1(nullCheck), uncheckedWriteBytesWithLength(bytebuf));
181
+ }
182
+
127
183
  function checkedWriteSignedInt(bytebuf) {
128
184
  return f.partial1(f.condition1(number, intTooBig), uncheckedWriteVNum(bytebuf));
129
185
  }
@@ -209,6 +265,19 @@
209
265
  }
210
266
  }
211
267
 
268
+ function uncheckedWriteBytesWithLength(bytebuf) {
269
+ return function(bytes) {
270
+ var buffNumBytes = f.existy(bytes) ? Buffer.byteLength(bytes) : 0;
271
+ var offsetAfterBytes = doEncodeVInt(bytebuf, buffNumBytes);
272
+ if (buffNumBytes > 0) {
273
+ bytebuf = bytebufOverflowProtect(bytebuf, bytes.length);
274
+ var targetStart = bytebuf.offset;
275
+ bytes.copy(bytebuf.buf, targetStart);
276
+ }
277
+ return targetStart + buffNumBytes;
278
+ }
279
+ }
280
+
212
281
  function doDecodeUByte(bytebuf) {
213
282
  return uncheckedReadUByte(bytebuf)();
214
283
  }
@@ -253,6 +322,68 @@
253
322
  return uncheckedReadShort(bytebuf)();
254
323
  }
255
324
 
325
+ function doDecodeProtobuf(bytebuf,protostreamTypename,root){
326
+ var wrappedObject = _.compose(decodeProtobufMessage(WrappedMessage),trimBytebuf)(bytebuf);
327
+ return unwrapWrappedMessage(wrappedObject,protostreamTypename,root);
328
+ }
329
+
330
+ function unwrapWrappedMessage(wrappedObject,protostreamTypename,root){
331
+ switch(true){
332
+ case _.has(wrappedObject,'wrappedDouble'):
333
+ return wrappedObject.wrappedDouble;
334
+ case _.has(wrappedObject,'wrappedString'):
335
+ return wrappedObject.wrappedString;
336
+ case _.has(wrappedObject,'wrappedBool'):
337
+ return wrappedObject.wrappedBool;
338
+ case _.has(wrappedObject,'wrappedBytes'):
339
+ return wrappedObject.wrappedBytes;
340
+ case _.has(wrappedObject,'wrappedMessage'):
341
+ var messageBytes= wrappedObject.wrappedMessage;
342
+ var protobufRoot = findRootByTypeId(protostreamTypename,root)(wrappedObject.wrappedTypeId);
343
+ return decodeProtobufMessage(protobufRoot)(messageBytes);
344
+ }
345
+ }
346
+
347
+ function decodeProtobufMessage(root){
348
+ return function(bytebuf){
349
+ return root.decode(bytebuf);
350
+ }
351
+ }
352
+
353
+ function findRootByTypeId(protostreamTypename,root){
354
+ return function(wrappedTypeId){
355
+ return _.compose(root,protostreamTypename)(wrappedTypeId);
356
+ }
357
+ }
358
+
359
+ function trimBytebuf(bytebuf,length){
360
+ if(!f.existy(length)) length = doDecodeVInt(bytebuf);
361
+ var retBuf = bytebuf.buf.slice(bytebuf.offset, bytebuf.offset + length);
362
+ bytebuf.offset += length;
363
+ return retBuf;
364
+ }
365
+
366
+ function doDecodeQuery(bytebuf,protostreamTypename,root){
367
+ var queryResponse = decodeProtobufMessage(Query.QueryResponse)(trimBytebuf(bytebuf));
368
+ var queryResults = queryResponse.results;
369
+ var projectionSize = queryResponse.projectionSize;
370
+ return f.greaterThan(0)(projectionSize) ? unwrapQueryWithProj(queryResults,projectionSize) : unwrapQueryWithoutProj(queryResults,protostreamTypename,root);
371
+ }
372
+
373
+ function decodeWrappedBytes(result,protostreamTypename,root){
374
+ return _.compose(f.curry3(unwrapWrappedMessage)(root)(protostreamTypename),decodeProtobufMessage(WrappedMessage))(result.wrappedBytes);
375
+ }
376
+
377
+ function unwrapQueryWithoutProj(queryResults,protostreamTypeName,root){
378
+ return queryResults.map(f.curry3(decodeWrappedBytes)(root)(protostreamTypeName));
379
+ }
380
+
381
+ function unwrapQueryWithProj(queryResults,projectionSize){
382
+ return _.reduce(queryResults,function(acc,cur,i){
383
+ return ((i%projectionSize) ? acc[acc.length-1].push(_.values(cur)[0]) : acc.push([_.values(cur)[0]])) && acc;
384
+ },[]);
385
+ }
386
+
256
387
  function uncheckedReadUByte(bytebuf) {
257
388
  return function() {
258
389
  if (1 > bytebuf.buf.length - bytebuf.offset) {
@@ -346,4 +477,24 @@
346
477
  }
347
478
  }
348
479
 
480
+ var WrappedMessage = (function() {
481
+ var root=protobuf.loadSync(path.join(__dirname+'/protostream/message-wrapping.proto'));
482
+
483
+ var wrappedMessage = root.lookupType('org.infinispan.protostream.WrappedMessage');
484
+
485
+ return wrappedMessage;
486
+ }());
487
+
488
+ var Query = (function() {
489
+ var root=protobuf.loadSync(path.join(__dirname+'/protostream/query.proto'));
490
+ protobuf.loadSync(path.join(__dirname+'/protostream/message-wrapping.proto'),root); //loaded the wrappedMessage.proto to the root
491
+ var QueryRequest = root.lookupType('org.infinispan.query.remote.client.QueryRequest');
492
+ var QueryResponse = root.lookupType('org.infinispan.query.remote.client.QueryResponse');
493
+
494
+ return {
495
+ QueryRequest,
496
+ QueryResponse
497
+ };
498
+ }());
499
+
349
500
  }.call(this));
package/lib/infinispan.js CHANGED
@@ -24,6 +24,7 @@
24
24
  logger.debugf('Using protocol version: %s', version);
25
25
 
26
26
  switch (version) {
27
+ case '3.0': return protocols.version30(clientOpts);
27
28
  case '2.9': return protocols.version29(clientOpts);
28
29
  case '2.5': return protocols.version25(clientOpts);
29
30
  case '2.2': return protocols.version22(clientOpts);
@@ -225,6 +226,23 @@
225
226
  var decoder = p.decodeValue();
226
227
  return futureKey(ctx, 0x03, k, p.encodeKey(k), decoder);
227
228
  },
229
+ /**
230
+ * Query the server with the given queryString.
231
+ *
232
+ * @param q {(Object)} query to retrieve.
233
+ * @returns {module:promise.Promise.<?Object[]>}
234
+ * A promise that will be completed with the array of values associated with
235
+ * the query, or empty array if the no values matches the query.
236
+ * @memberof Client#
237
+ * @since 1.3
238
+ */
239
+ query: function(q) {
240
+ //TODO : extend the support of query with application/json datatypes
241
+ var ctx = transport.context(SMALL);
242
+ logger.debugf('Invoke query(msgId=%d,key=%s)', ctx.id, u.str(q));
243
+ var decoder = p.decodeQuery();
244
+ return futureKey(ctx, 0x1F, q, p.encodeQuery(q), decoder);
245
+ },
228
246
  /**
229
247
  * Check whether the given key is present.
230
248
  *
@@ -564,7 +582,7 @@
564
582
  ping: function() {
565
583
  var ctx = transport.context(TINY);
566
584
  logger.debugf('Invoke ping(msgId=%d)', ctx.id);
567
- return futureDecodeOnly(ctx, 0x17, p.decodeServerMediaTypes);
585
+ return futureDecodeOnly(ctx, 0x17, p.decodePingResponse);
568
586
  },
569
587
 
570
588
  /**
@@ -735,6 +753,14 @@
735
753
  */
736
754
  toString: function() {
737
755
  return util.format('Client(%s)', transport);
756
+ },
757
+
758
+ registerProtostreamType: function(typeName,descriptorId){
759
+ return p.registerProtostreamType(typeName,descriptorId);
760
+ },
761
+
762
+ registerProtostreamRoot: function(root){
763
+ return p.registerProtostreamRoot(root);
738
764
  }
739
765
  }
740
766
  };
@@ -879,6 +905,12 @@
879
905
  * @property {?String} ssl.sniHostName - Optional SNI host name.
880
906
  * @property {?String} ssl.cryptoStore.path - Optional crypto store path.
881
907
  * @property {?String} ssl.cryptoStore.passphrase - Optional password for crypto store.
908
+ * @property {?boolean} authentication.enabled - Enable authentication.
909
+ * @property {?String} authentication.saslMechanism - Select the SASL mechanism to use. Can be one of PLAIN, DIGEST-MD5, SCRAM-SHA-1, SCRAM-SHA-256, SCRAM-SHA-384, SCRAM-SHA-512, EXTERNAL, OAUTHBEARER
910
+ * @property {?String} authentication.userName - The authentication username. Required by the PLAIN, DIGEST and SCRAM mechanisms.
911
+ * @property {?String} authentication.password - The authentication password. Required by the PLAIN, DIGEST and SCRAM mechanisms.
912
+ * @property {?String} authentication.token - The OAuth token. Required by the OAUTHBEARER mechanism.
913
+ * @property {?String} authentication.authzid - The SASL authorization ID.
882
914
  * @property {?boolean} [topologyUpdates=true] - Optional flag to controls whether the client deals with topology updates or not.
883
915
  * @property {?(text/plain|application/json)} [mediaType=text/plain] - Media type of the cache contents.
884
916
  * @property {?Cluster[]} clusters - Optional additional clusters for cross-site failovers.
package/lib/io.js CHANGED
@@ -7,9 +7,6 @@
7
7
  var fs = require('fs');
8
8
  var net = require('net');
9
9
 
10
- var promiseFinally = require('promise.prototype.finally');
11
- promiseFinally.shim(); // will be a no-op if not needed
12
-
13
10
  var tls = require('tls');
14
11
  var util = require('util');
15
12
 
@@ -259,10 +256,19 @@
259
256
  });
260
257
  },
261
258
  write: function(buffer) {
262
- var flushed = sock.write(buffer);
263
- if (!flushed)
264
- logger.debugf('Buffer write not fully flushed, part of of data queued for: %s',
265
- buffer.toString('hex').toUpperCase());
259
+ return new Promise(function (fulfill, reject) {
260
+ var flushed = sock.write(buffer, (err) => {
261
+ if (err) {
262
+ logger.error('Error writing to socket: %s', err);
263
+ transport.retryRpcs(addr); // retry RPCs in case of error
264
+ }
265
+ fulfill();
266
+ });
267
+ if (!flushed)
268
+ logger.debugf('Buffer write not fully flushed, part of of data queued for: %s',
269
+ buffer.toString('hex').toUpperCase());
270
+ });
271
+
266
272
  },
267
273
  getAddress: function() {
268
274
  return addr;
@@ -745,7 +751,7 @@
745
751
  logger.debugf('Invoke ping(msgId=%d)', ctx.id);
746
752
  var p = transport.getProtocol();
747
753
  f.actions(p.stepsHeader(ctx, 0x17, undefined), codec.bytesEncoded)(ctx);
748
- return transport.writeCommandPinned(ctx, p.decodeServerMediaTypes, conn);
754
+ return transport.writeCommandPinned(ctx, p.decodePingResponse, conn);
749
755
  }
750
756
 
751
757
  function auth(transport, conn, topologyId) {
@@ -758,16 +764,17 @@
758
764
  ctx.topologyId = topologyId;
759
765
  var p = transport.getProtocol();
760
766
  logger.debugf('Invoke auth(msgId=%d)', ctx.id);
761
- f.actions(p.stepsHeaderBody(ctx, 0x23, p.sasl(transport.authOpts()), undefined), codec.bytesEncoded)(ctx);
767
+ var holder = {};
768
+ f.actions(p.stepsHeaderBody(ctx, 0x23, p.sasl(transport.authOpts(), holder), undefined), codec.bytesEncoded)(ctx);
762
769
  var result = transport.writeCommandPinned(ctx, p.decodeSasl, conn);
763
-
764
770
  return result.then(function (r) {
765
- if(r.challenge > 0) {
766
- f.actions(p.stepsHeaderBody(ctx, 0x23, p.sasl(transport.authOpts(), r.response), undefined), codec.bytesEncoded)(ctx);
767
- return transport.writeCommandPinned(ctx, p.decodeSasl, conn).then(function (r) {
768
- return r;
769
- });
770
- }
771
+ ctx = u.context(16);
772
+ ctx.topologyId = topologyId;
773
+ holder.challenge = r.response;
774
+ f.actions(p.stepsHeaderBody(ctx, 0x23, p.sasl(transport.authOpts(), holder) , undefined), codec.bytesEncoded)(ctx);
775
+ return transport.writeCommandPinned(ctx, p.decodeSasl, conn).then(function (r) {
776
+ return r;
777
+ });
771
778
  return r;
772
779
  });
773
780
  }