Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: redis/ioredis
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.28.1
Choose a base ref
...
head repository: redis/ioredis
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.28.2
Choose a head ref
  • 8 commits
  • 17 files changed
  • 3 contributors

Commits on Nov 24, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e5615da View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f5d8b73 View commit details

Commits on Nov 28, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b817747 View commit details
  2. chore: scanStream TYPE test requires redis 6 (#1469)

    See https://redis.io/commands/scan
    
    When this test fails in local development
    it stops the rest of the tests from running.
    Some OSes have redis 5 or older installed.
    TysonAndre authored Nov 28, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d1ead14 View commit details

Commits on Nov 30, 2021

  1. fix: add Redis campaign (#1475)

    Also release other pending fixes.
    luin authored Nov 30, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3f3d8e9 View commit details
  2. docs(README): update Redis title

    luin committed Nov 30, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3030eee View commit details

Commits on Dec 1, 2021

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a9059be View commit details
  2. chore(release): 4.28.2 [skip ci]

    ## [4.28.2](v4.28.1...v4.28.2) (2021-12-01)
    
    ### Bug Fixes
    
    * add Redis campaign ([#1475](#1475)) ([3f3d8e9](3f3d8e9))
    * fix a memory leak with autopipelining. ([#1470](#1470)) ([f5d8b73](f5d8b73))
    * unhandled Promise rejections in pipeline.exec [skip ci] ([#1466](#1466)) ([e5615da](e5615da))
    semantic-release-bot committed Dec 1, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    61e98b4 View commit details
4 changes: 1 addition & 3 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
@@ -34,9 +34,7 @@ rules:
"@typescript-eslint/no-unused-vars":
- warn
- args: none
"@typescript-eslint/interface-name-prefix":
- error
- "always"
"@typescript-eslint/interface-name-prefix": 0

overrides:
- files: ["{test,benchmarks}/**/*"]
9 changes: 9 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## [4.28.2](https://github.com/luin/ioredis/compare/v4.28.1...v4.28.2) (2021-12-01)


### Bug Fixes

* add Redis campaign ([#1475](https://github.com/luin/ioredis/issues/1475)) ([3f3d8e9](https://github.com/luin/ioredis/commit/3f3d8e9eb868f4e58bb63926d3b683d9892835f2))
* fix a memory leak with autopipelining. ([#1470](https://github.com/luin/ioredis/issues/1470)) ([f5d8b73](https://github.com/luin/ioredis/commit/f5d8b73c747a0db5cb36e83e6fe022a19a544bd2))
* unhandled Promise rejections in pipeline.exec [skip ci] ([#1466](https://github.com/luin/ioredis/issues/1466)) ([e5615da](https://github.com/luin/ioredis/commit/e5615da8786956df08a9b33b6cd4dd31e6eaa759))

## [4.28.1](https://github.com/luin/ioredis/compare/v4.28.0...v4.28.1) (2021-11-23)


18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -45,15 +45,23 @@ used in the world's biggest online commerce company [Alibaba](http://www.alibaba

# Sponsors

<a href="https://github.com/sponsors/luin">Become a sponsor!</a>

### Upstash: Serverless Database for Redis

<a href="https://upstash.com/?utm_source=ioredis"><img align="right" width="320" src="resources/upstash.png" alt="Upstash"></a>

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.

[Start for free in 30 seconds! ](https://upstash.com/?utm_source=ioredis)
[Start for free in 30 seconds!](https://upstash.com/?utm_source=ioredis)

<br clear="both"/>

### Redis Cloud: From the creators of Redis

<a href="https://redis.info/ioredis-tryfree"><img align="right" width="320" src="resources/redis-tryfree.png" alt="redis-tryfree"></a>

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!

[Sign Up Now!](https://redis.info/ioredis-tryfree)

<br clear="both"/>

@@ -74,9 +82,7 @@ Medis starts with all the basic features you need:

[Medis 1 is open sourced on GitHub](https://github.com/luin/medis)

### Kuber: Kubernetes Dashboard for iOS

<a href="http://bit.ly/kuber-ios"><img src="resources/kuber.png" alt="Download on the App Store"></a>
<br clear="both"/>

<hr>

8 changes: 6 additions & 2 deletions lib/autoPipelining.ts
Original file line number Diff line number Diff line change
@@ -45,6 +45,10 @@ function executeAutoPipeline(client, slotKey: string) {
client._autoPipelines.delete(slotKey);

const callbacks = pipeline[kCallbacks];
// Stop keeping a reference to callbacks immediately after the callbacks stop being used.
// This allows the GC to reclaim objects referenced by callbacks, especially with 16384 slots
// in Redis.Cluster
pipeline[kCallbacks] = null;

// Perform the call
pipeline.exec(function (err, results) {
@@ -175,9 +179,9 @@ export function executeWithAutoPipelining(
setImmediate(executeAutoPipeline, client, slotKey);
}

// Create the promise which will execute the
// Create the promise which will execute the command in the pipeline.
const autoPipelinePromise = new CustomPromise(function (resolve, reject) {
pipeline[kCallbacks].push(function (err, value) {
pipeline[kCallbacks].push(function (err: Error | null, value: any) {
if (err) {
reject(err);
return;
17 changes: 10 additions & 7 deletions lib/command.ts
Original file line number Diff line number Diff line change
@@ -101,13 +101,16 @@ export default class Command implements ICommand {

private static getFlagMap(): IFlagMap {
if (!this.flagMap) {
this.flagMap = Object.keys(Command.FLAGS).reduce((map, flagName) => {
map[flagName] = {};
Command.FLAGS[flagName].forEach((commandName) => {
map[flagName][commandName] = true;
});
return map;
}, {});
this.flagMap = Object.keys(Command.FLAGS).reduce(
(map: IFlagMap, flagName: string) => {
map[flagName] = {};
Command.FLAGS[flagName].forEach((commandName: string) => {
map[flagName][commandName] = true;
});
return map;
},
{}
);
}
return this.flagMap;
}
33 changes: 22 additions & 11 deletions lib/pipeline.ts
Original file line number Diff line number Diff line change
@@ -240,7 +240,15 @@ Pipeline.prototype.execBuffer = deprecate(function () {
return execBuffer.apply(this, arguments);
}, "Pipeline#execBuffer: Use Pipeline#exec instead");

Pipeline.prototype.exec = function (callback: CallbackFunction) {
// NOTE: To avoid an unhandled promise rejection, this will unconditionally always return this.promise,
// which always has the rejection handled by standard-as-callback
// adding the provided rejection callback.
//
// If a different promise instance were returned, that promise would cause its own unhandled promise rejection
// errors, even if that promise unconditionally resolved to **the resolved value of** this.promise.
Pipeline.prototype.exec = function (
callback: CallbackFunction
): Promise<Array<any>> {
// Wait for the cluster to be connected, since we need nodes information before continuing
if (this.isCluster && !this.redis.slots.length) {
if (this.redis.status === "wait") this.redis.connect().catch(noop);
@@ -338,17 +346,19 @@ Pipeline.prototype.exec = function (callback: CallbackFunction) {

// In cluster mode, always load scripts before running the pipeline
if (this.isCluster) {
return pMap(scripts, (script) => _this.redis.script("load", script.lua), {
pMap(scripts, (script) => _this.redis.script("load", script.lua), {
concurrency: 10,
}).then(function () {
for (let i = 0; i < scripts.length; i++) {
_this.redis._addedScriptHashes[scripts[i].sha] = true;
}
return execPipeline();
});
})
.then(function () {
for (let i = 0; i < scripts.length; i++) {
_this.redis._addedScriptHashes[scripts[i].sha] = true;
}
})
.then(execPipeline, this.reject);
return this.promise;
}

return this.redis
this.redis
.script(
"exists",
scripts.map(({ sha }) => sha)
@@ -371,8 +381,9 @@ Pipeline.prototype.exec = function (callback: CallbackFunction) {
for (let i = 0; i < scripts.length; i++) {
_this.redis._addedScriptHashes[scripts[i].sha] = true;
}
return execPipeline();
});
})
.then(execPipeline, this.reject);
return this.promise;

function execPipeline() {
let data = "";
2 changes: 2 additions & 0 deletions lib/redis/RedisOptions.ts
Original file line number Diff line number Diff line change
@@ -30,6 +30,8 @@ export interface IRedisOptions
enableAutoPipelining?: boolean;
autoPipeliningIgnoredCommands?: string[];
maxScriptsCachingTime?: number;
offlineQueue?: boolean;
commandQueue?: boolean;
}

export const DEFAULT_REDIS_OPTIONS: IRedisOptions = {
25 changes: 16 additions & 9 deletions lib/redis/index.ts
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ import {
ReconnectOnError,
DEFAULT_REDIS_OPTIONS,
} from "./RedisOptions";
import { NetStream } from "../types";
import { NetStream, CallbackFunction, ICommandItem } from "../types";

const debug = Debug("redis");

@@ -339,7 +339,7 @@ Redis.prototype.connect = function (callback) {
this.connector.connect(function (type, err) {
_this.silentEmit(type, err);
}) as Promise<NetStream>,
function (err, stream) {
function (err: Error | null, stream?: NetStream) {
if (err) {
_this.flushQueue(err);
_this.silentEmit("error", err);
@@ -473,17 +473,24 @@ Redis.prototype.end = function () {
*
* @public
*/
Redis.prototype.duplicate = function (override) {
Redis.prototype.duplicate = function (override: IRedisOptions) {
return new Redis(Object.assign({}, this.options, override || {}));
};

Redis.prototype.recoverFromFatalError = function (commandError, err, options) {
Redis.prototype.recoverFromFatalError = function (
commandError,
err: Error | null,
options
) {
this.flushQueue(err, options);
this.silentEmit("error", err);
this.disconnect(true);
};

Redis.prototype.handleReconnection = function handleReconnection(err, item) {
Redis.prototype.handleReconnection = function handleReconnection(
err: Error,
item: ICommandItem
) {
let needReconnect: ReturnType<ReconnectOnError> = false;
if (this.options.reconnectOnError) {
needReconnect = this.options.reconnectOnError(err);
@@ -521,7 +528,7 @@ Redis.prototype.handleReconnection = function handleReconnection(err, item) {
* @param {object} options
* @private
*/
Redis.prototype.flushQueue = function (error, options) {
Redis.prototype.flushQueue = function (error: Error, options: IRedisOptions) {
options = defaults({}, options, {
offlineQueue: true,
commandQueue: true,
@@ -555,9 +562,9 @@ Redis.prototype.flushQueue = function (error, options) {
* @param {Function} callback
* @private
*/
Redis.prototype._readyCheck = function (callback) {
Redis.prototype._readyCheck = function (callback: CallbackFunction) {
const _this = this;
this.info(function (err, res) {
this.info(function (err: Error | null, res: string) {
if (err) {
return callback(err);
}
@@ -710,7 +717,7 @@ addTransactionSupport(Redis.prototype);
* ```
* @private
*/
Redis.prototype.sendCommand = function (command: Command, stream) {
Redis.prototype.sendCommand = function (command: Command, stream: NetStream) {
if (this.status === "wait") {
this.connect().catch(noop);
}
2 changes: 1 addition & 1 deletion lib/script.ts
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ export default class Script {
const result = container.sendCommand(evalsha);
if (isPromise(result)) {
return asCallback(
result.catch((err) => {
result.catch((err: Error) => {
if (err.toString().indexOf("NOSCRIPT") === -1) {
throw err;
}
8 changes: 4 additions & 4 deletions lib/transaction.ts
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ export function addTransactionSupport(redis) {
}
const promise = exec.call(pipeline);
return asCallback(
promise.then(function (result) {
promise.then(function (result: any[]): any[] | null {
const execResult = result[result.length - 1];
if (typeof execResult === "undefined") {
throw new Error(
@@ -80,7 +80,7 @@ export function addTransactionSupport(redis) {
};

const { execBuffer } = pipeline;
pipeline.execBuffer = function (callback) {
pipeline.execBuffer = function (callback: CallbackFunction) {
if (this._transactions > 0) {
execBuffer.call(pipeline);
}
@@ -90,9 +90,9 @@ export function addTransactionSupport(redis) {
};

const { exec } = redis;
redis.exec = function (callback: CallbackFunction) {
redis.exec = function (callback: CallbackFunction): Promise<any[] | null> {
return asCallback(
exec.call(this).then(function (results) {
exec.call(this).then(function (results: any[] | null) {
if (Array.isArray(results)) {
results = wrapMultiResult(results);
}
Loading