ioredis 4.28.1 → 4.28.2

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.
package/Changelog.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## [4.28.2](https://github.com/luin/ioredis/compare/v4.28.1...v4.28.2) (2021-12-01)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add Redis campaign ([#1475](https://github.com/luin/ioredis/issues/1475)) ([3f3d8e9](https://github.com/luin/ioredis/commit/3f3d8e9eb868f4e58bb63926d3b683d9892835f2))
7
+ * fix a memory leak with autopipelining. ([#1470](https://github.com/luin/ioredis/issues/1470)) ([f5d8b73](https://github.com/luin/ioredis/commit/f5d8b73c747a0db5cb36e83e6fe022a19a544bd2))
8
+ * unhandled Promise rejections in pipeline.exec [skip ci] ([#1466](https://github.com/luin/ioredis/issues/1466)) ([e5615da](https://github.com/luin/ioredis/commit/e5615da8786956df08a9b33b6cd4dd31e6eaa759))
9
+
1
10
  ## [4.28.1](https://github.com/luin/ioredis/compare/v4.28.0...v4.28.1) (2021-11-23)
2
11
 
3
12
 
package/README.md CHANGED
@@ -45,15 +45,23 @@ used in the world's biggest online commerce company [Alibaba](http://www.alibaba
45
45
 
46
46
  # Sponsors
47
47
 
48
- <a href="https://github.com/sponsors/luin">Become a sponsor!</a>
49
-
50
48
  ### Upstash: Serverless Database for Redis
51
49
 
52
50
  <a href="https://upstash.com/?utm_source=ioredis"><img align="right" width="320" src="resources/upstash.png" alt="Upstash"></a>
53
51
 
54
52
  Upstash is a Serverless Database with Redis/REST API and durable storage. It is the perfect database for your applications thanks to its per request pricing and low latency data.
55
53
 
56
- [Start for free in 30 seconds! ](https://upstash.com/?utm_source=ioredis)
54
+ [Start for free in 30 seconds!](https://upstash.com/?utm_source=ioredis)
55
+
56
+ <br clear="both"/>
57
+
58
+ ### Redis Cloud: From the creators of Redis
59
+
60
+ <a href="https://redis.info/ioredis-tryfree"><img align="right" width="320" src="resources/redis-tryfree.png" alt="redis-tryfree"></a>
61
+
62
+ Experience the best Redis. For a limited time, sign up to Redis Enterprise Cloud and use **MATRIX200** to get $200 credits, and a chance to win a Tesla!
63
+
64
+ [Sign Up Now!](https://redis.info/ioredis-tryfree)
57
65
 
58
66
  <br clear="both"/>
59
67
 
@@ -74,9 +82,7 @@ Medis starts with all the basic features you need:
74
82
 
75
83
  [Medis 1 is open sourced on GitHub](https://github.com/luin/medis)
76
84
 
77
- ### Kuber: Kubernetes Dashboard for iOS
78
-
79
- <a href="http://bit.ly/kuber-ios"><img src="resources/kuber.png" alt="Download on the App Store"></a>
85
+ <br clear="both"/>
80
86
 
81
87
  <hr>
82
88
 
@@ -42,6 +42,10 @@ function executeAutoPipeline(client, slotKey) {
42
42
  const pipeline = client._autoPipelines.get(slotKey);
43
43
  client._autoPipelines.delete(slotKey);
44
44
  const callbacks = pipeline[exports.kCallbacks];
45
+ // Stop keeping a reference to callbacks immediately after the callbacks stop being used.
46
+ // This allows the GC to reclaim objects referenced by callbacks, especially with 16384 slots
47
+ // in Redis.Cluster
48
+ pipeline[exports.kCallbacks] = null;
45
49
  // Perform the call
46
50
  pipeline.exec(function (err, results) {
47
51
  client._runningAutoPipelines.delete(slotKey);
@@ -139,7 +143,7 @@ function executeWithAutoPipelining(client, functionName, commandName, args, call
139
143
  */
140
144
  setImmediate(executeAutoPipeline, client, slotKey);
141
145
  }
142
- // Create the promise which will execute the
146
+ // Create the promise which will execute the command in the pipeline.
143
147
  const autoPipelinePromise = new CustomPromise(function (resolve, reject) {
144
148
  pipeline[exports.kCallbacks].push(function (err, value) {
145
149
  if (err) {
package/built/pipeline.js CHANGED
@@ -213,6 +213,12 @@ Pipeline.prototype.execBuffer = util_1.deprecate(function () {
213
213
  }
214
214
  return execBuffer.apply(this, arguments);
215
215
  }, "Pipeline#execBuffer: Use Pipeline#exec instead");
216
+ // NOTE: To avoid an unhandled promise rejection, this will unconditionally always return this.promise,
217
+ // which always has the rejection handled by standard-as-callback
218
+ // adding the provided rejection callback.
219
+ //
220
+ // If a different promise instance were returned, that promise would cause its own unhandled promise rejection
221
+ // errors, even if that promise unconditionally resolved to **the resolved value of** this.promise.
216
222
  Pipeline.prototype.exec = function (callback) {
217
223
  // Wait for the cluster to be connected, since we need nodes information before continuing
218
224
  if (this.isCluster && !this.redis.slots.length) {
@@ -286,16 +292,18 @@ Pipeline.prototype.exec = function (callback) {
286
292
  }
287
293
  // In cluster mode, always load scripts before running the pipeline
288
294
  if (this.isCluster) {
289
- return pMap(scripts, (script) => _this.redis.script("load", script.lua), {
295
+ pMap(scripts, (script) => _this.redis.script("load", script.lua), {
290
296
  concurrency: 10,
291
- }).then(function () {
297
+ })
298
+ .then(function () {
292
299
  for (let i = 0; i < scripts.length; i++) {
293
300
  _this.redis._addedScriptHashes[scripts[i].sha] = true;
294
301
  }
295
- return execPipeline();
296
- });
302
+ })
303
+ .then(execPipeline, this.reject);
304
+ return this.promise;
297
305
  }
298
- return this.redis
306
+ this.redis
299
307
  .script("exists", scripts.map(({ sha }) => sha))
300
308
  .then(function (results) {
301
309
  const pending = [];
@@ -313,8 +321,9 @@ Pipeline.prototype.exec = function (callback) {
313
321
  for (let i = 0; i < scripts.length; i++) {
314
322
  _this.redis._addedScriptHashes[scripts[i].sha] = true;
315
323
  }
316
- return execPipeline();
317
- });
324
+ })
325
+ .then(execPipeline, this.reject);
326
+ return this.promise;
318
327
  function execPipeline() {
319
328
  let data = "";
320
329
  let buffers;
@@ -97,7 +97,7 @@ function wrapMultiResult(arr) {
97
97
  }
98
98
  exports.wrapMultiResult = wrapMultiResult;
99
99
  /**
100
- * Detect the argument is a int
100
+ * Detect if the argument is a int
101
101
  *
102
102
  * @param {string} value
103
103
  * @return {boolean} Whether the value is a int
@@ -174,7 +174,7 @@ exports.timeout = timeout;
174
174
  */
175
175
  function convertObjectToArray(obj) {
176
176
  const result = [];
177
- const keys = Object.keys(obj);
177
+ const keys = Object.keys(obj); // Object.entries requires node 7+
178
178
  for (let i = 0, l = keys.length; i < l; i++) {
179
179
  result.push(keys[i], obj[keys[i]]);
180
180
  }
@@ -188,7 +188,7 @@ exports.convertObjectToArray = convertObjectToArray;
188
188
  * @return {array}
189
189
  * @example
190
190
  * ```js
191
- * > convertObjectToArray(new Map([[1, '2']]))
191
+ * > convertMapToArray(new Map([[1, '2']]))
192
192
  * [1, '2']
193
193
  * ```
194
194
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ioredis",
3
- "version": "4.28.1",
3
+ "version": "4.28.2",
4
4
  "description": "A robust, performance-focused and full-featured Redis client for Node.js.",
5
5
  "main": "built/index.js",
6
6
  "files": [