Skip to content

Commit

Permalink
fix: flushall should mutate data, not fork it (#1125)
Browse files Browse the repository at this point in the history
  • Loading branch information
stipsan authored Jan 28, 2022
1 parent b0e02e1 commit 45fc377
Show file tree
Hide file tree
Showing 340 changed files with 18,206 additions and 6,032 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
{
"files": ["test/integration/**/*.js"],
"rules": {
"import/no-relative-parent-imports": ["error"]
"import/no-relative-parent-imports": ["error"],
"arrow-body-style": ["error", "always"]
}
}
]
Expand Down
41 changes: 32 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ jobs:
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
- name: npm install, build and lint
run: |
npm ci
npm run lint
- name: Install dependencies
run: npm ci
- name: lint, prettier --check
run: npm run lint
test:
name: Test on node ${{ matrix.node_version }} and ${{ matrix.os }}
runs-on: ${{ matrix.os }}
Expand All @@ -36,10 +36,10 @@ jobs:
uses: actions/setup-node@master
with:
node-version: ${{ matrix.node_version }}

- name: npm install, build and test
- name: Install dependencies
run: npm ci
- name: build:lib, test:integration
run: |
npm ci
npm run build:lib
npm run test:integration
Expand All @@ -55,8 +55,31 @@ jobs:
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
- name: npm install, build and lint
- name: Install dependencies
run: npm ci
- name: build:browser.js, test:browser.js
run: |
npm ci
npm run build:browser.js
npm run test:browser.js
e2e:
name: Run integration tests on real redis
runs-on: ubuntu-latest
needs: [build]
services:
redis:
image: redis
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- uses: actions/checkout@master
- uses: actions/setup-node@master
- name: Install dependencies
run: npm ci
- name: test:e2e
run: npm run test:e2e -- --detectOpenHandles
94 changes: 47 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Check the [compatibility table](compat.md) for supported redis commands.
## Usage ([try it in your browser with RunKit](https://runkit.com/npm/ioredis-mock))

```js
const Redis = require('ioredis-mock');
const Redis = require('ioredis-mock')
const redis = new Redis({
// `options.data` does not exist in `ioredis`, only `ioredis-mock`
data: {
Expand All @@ -36,7 +36,7 @@ const redis = new Redis({
'user:1': { id: '1', username: 'superman', email: '[email protected]' },
'user:2': { id: '2', username: 'batman', email: '[email protected]' },
},
});
})
// Basically use it just like ioredis
```

Expand All @@ -45,57 +45,57 @@ const redis = new Redis({
There's a browser build available. You can import it directly (`import Redis from 'ioredis-mock/browser.js'`), or use it on unpkg.com:

```js
import Redis from 'https://unpkg.com/ioredis-mock';
import Redis from 'https://unpkg.com/ioredis-mock'

const redis = new Redis();
redis.set('foo', 'bar');
console.log(await redis.get('foo'));
const redis = new Redis()
redis.set('foo', 'bar')
console.log(await redis.get('foo'))
```

### Breaking API changes from v5

Before v6, each instance of `ioredis-mock` lived in isolation:

```js
const Redis = require('ioredis-mock');
const redis1 = new Redis();
const redis2 = new Redis();
const Redis = require('ioredis-mock')
const redis1 = new Redis()
const redis2 = new Redis()

await redis1.set('foo', 'bar');
console.log(await redis1.get('foo'), await redis2.get('foo')); // 'bar', null
await redis1.set('foo', 'bar')
console.log(await redis1.get('foo'), await redis2.get('foo')) // 'bar', null
```

In v6 the [internals were rewritten](https://github.com/stipsan/ioredis-mock/pull/1110) to behave more like real life redis, if the host and port is the same, the context is now shared:

```js
const Redis = require('ioredis-mock');
const redis1 = new Redis();
const redis2 = new Redis();
const redis3 = new Redis({ port: 6380 }); // 6379 is the default port
const Redis = require('ioredis-mock')
const redis1 = new Redis()
const redis2 = new Redis()
const redis3 = new Redis({ port: 6380 }) // 6379 is the default port

await redis1.set('foo', 'bar');
await redis1.set('foo', 'bar')
console.log(
await redis1.get('foo'), // 'bar'
await redis2.get('foo'), // 'bar'
await redis3.get('foo') // null
);
)
```

And since `ioredis-mock` now persist data between instances, you'll [likely](https://github.com/luin/ioredis/blob/8278ec0a435756c54ba4f98587aec1a913e8b7d3/test/helpers/global.ts#L8) need to run `flushall` between testing suites:

```js
const Redis = require('ioredis-mock');
const Redis = require('ioredis-mock')

afterEach((done) => {
new Redis().flushall().then(() => done());
});
afterEach(done => {
new Redis().flushall().then(() => done())
})
```

#### `createConnectedClient` is deprecated

Replace it with `.duplicate()` or use another `new Redis` instance.

### `ioredis-mock/jest.js` is deprecated
#### `ioredis-mock/jest.js` is deprecated

`ioredis-mock` is no longer doing a `import { Command } from 'ioredis'` internally, it's now doing a direct import `import Command from 'ioredis/built/command'` and thus the `jest.js` [workaround](https://github.com/stipsan/ioredis-mock/issues/568) is no longer needed:

Expand All @@ -110,26 +110,26 @@ We also support redis [publish/subscribe](https://redis.io/topics/pubsub) channe
Like [ioredis](https://github.com/luin/ioredis#pubsub), you need two clients:

```js
const Redis = require('ioredis-mock');
const redisPub = new Redis();
const redisSub = new Redis();
const Redis = require('ioredis-mock')
const redisPub = new Redis()
const redisSub = new Redis()

redisSub.on('message', (channel, message) => {
console.log(`Received ${message} from ${channel}`);
});
redisSub.subscribe('emails');
redisPub.publish('emails', '[email protected]');
console.log(`Received ${message} from ${channel}`)
})
redisSub.subscribe('emails')
redisPub.publish('emails', '[email protected]')
```

### Promises

By default, ioredis-mock uses the native Promise library. If you need (or prefer) [bluebird](http://bluebirdjs.com/) promises, set `Redis.Promise`:

```js
var Promise = require('bluebird');
var Redis = require('ioredis-mock');
var Promise = require('bluebird')
var Redis = require('ioredis-mock')

Redis.Promise = Promise;
Redis.Promise = Promise
```
### Lua scripting
Expand All @@ -142,26 +142,26 @@ You could define a custom command `multiply` which accepts one
key and one argument. A redis key, where you can get the multiplicand, and an argument which will be the multiplicator:
```js
const Redis = require('ioredis-mock');
const redis = new Redis({ data: { k1: 5 } });
const Redis = require('ioredis-mock')
const redis = new Redis({ data: { k1: 5 } })
const commandDefinition = {
numberOfKeys: 1,
lua: 'return redis.call("GET", KEYS[1]) * ARGV[1]',
};
redis.defineCommand('multiply', commandDefinition); // defineCommand(name, definition)
}
redis.defineCommand('multiply', commandDefinition) // defineCommand(name, definition)
// now we can call our brand new multiply command as an ordinary command
redis.multiply('k1', 10).then((result) => {
expect(result).toBe(5 * 10);
});
redis.multiply('k1', 10).then(result => {
expect(result).toBe(5 * 10)
})
```

You can also achieve the same effect by using the `eval` command:

```js
const Redis = require('ioredis-mock');
const redis = new Redis({ data: { k1: 5 } });
const result = redis.eval(`return redis.call("GET", "k1") * 10`);
expect(result).toBe(5 * 10);
const Redis = require('ioredis-mock')
const redis = new Redis({ data: { k1: 5 } })
const result = redis.eval(`return redis.call("GET", "k1") * 10`)
expect(result).toBe(5 * 10)
```

note we are calling the ordinary redis `GET` command by using the global `redis` object's `call` method.
Expand All @@ -178,11 +178,11 @@ As a difference from ioredis we currently don't support:
Work on Cluster support has started, the current implementation is minimal and PRs welcome #359

```js
const Redis = require('ioredis-mock');
const Redis = require('ioredis-mock')

const cluster = new Redis.Cluster(['redis://localhost:7001']);
const nodes = cluster.nodes;
expect(nodes.length).toEqual(1);
const cluster = new Redis.Cluster(['redis://localhost:7001'])
const nodes = cluster.nodes
expect(nodes.length).toEqual(1)
```

## [Roadmap](https://github.com/users/stipsan/projects/1/views/4)
Expand Down
2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = {
presets: [['@babel/env', { targets: { node: '10' }, bugfixes: true }]],
};
}
12 changes: 6 additions & 6 deletions browser-shims.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import hrtime from 'browser-process-hrtime';
import { Buffer } from 'buffer';
import hrtime from 'browser-process-hrtime'
import { Buffer } from 'buffer'

global.Buffer = Buffer;
global.Buffer = Buffer

export function nextTickShim(fn) {
Promise.resolve().then(() => {
fn();
});
fn()
})
}

export const hrtimeShim = hrtime;
export const hrtimeShim = hrtime
16 changes: 8 additions & 8 deletions example.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// declare peer dependencies so RunKit don't throw errors
require('ioredis/package.json');
require('redis-commands/package.json');
require('ioredis/package.json')
require('redis-commands/package.json')

const Redis = require('ioredis-mock');
const Redis = require('ioredis-mock')
const redis = new Redis({
data: {
user_next: '3',
Expand All @@ -13,19 +13,19 @@ const redis = new Redis({
'user:1': { id: '1', username: 'superman', email: '[email protected]' },
'user:2': { id: '2', username: 'batman', email: '[email protected]' },
},
});
})

async function main() {
const userNext = await redis.incr('user_next');
const userNext = await redis.incr('user_next')
await redis.hmset(
`user:${userNext}`,
new Map([
['id', userNext],
['username', 'wonderwoman'],
['email', '[email protected]'],
])
);
console.log(await redis.hgetall(`user:${userNext}`));
)
console.log(await redis.hgetall(`user:${userNext}`))
}

main();
main()
6 changes: 3 additions & 3 deletions jest.config.browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ module.exports = {
// @TODO tests need a rewrite before we can run them on browser.js (stream-mock is incompatible)
testPathIgnorePatterns: [
'test/integration/commands/hscanStream.js',
'test/integration/commands/zscanStream.js',
'test/integration/commands/sscanStream.js',
'test/integration/commands/scanStream.js',
'test/integration/commands/sscanStream.js',
'test/integration/commands/zscanStream.js',
'test/integration/keyprefix.js',
],
};
}
2 changes: 1 addition & 1 deletion jest.config.integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ module.exports = {
...require('./jest.config'),
testMatch: ['**/test/integration/**/*.js'],
setupFiles: ['<rootDir>/testSetupLib.js'],
};
}
2 changes: 1 addition & 1 deletion jest.config.jestlegacy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ module.exports = {
...require('./jest.config'),
testMatch: ['**/test/integration/**/*.js'],
setupFiles: ['<rootDir>/testSetupJestLegacy.js'],
};
}
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ module.exports = {
coverageDirectory: 'coverage',
setupFiles: ['<rootDir>/testSetupSrc.js'],
setupFilesAfterEnv: ['<rootDir>/testSetupAfterEnv.js'],
};
}
Loading

0 comments on commit 45fc377

Please sign in to comment.