Skip to content

fix #1970 - add support for RESTORE #2535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This folder contains example scripts showing how to use Node Redis in different scenarios.

| File Name | Description |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
| `blocking-list-pop.js` | Block until an element is pushed to a list. |
| `bloom-filter.js` | Space efficient set membership checks with a [Bloom Filter](https://en.wikipedia.org/wiki/Bloom_filter) using [RedisBloom](https://redisbloom.io). |
| `check-connection-status.js` | Check the client's connection status. |
Expand All @@ -12,6 +12,7 @@ This folder contains example scripts showing how to use Node Redis in different
| `connect-to-cluster.js` | Connect to a Redis cluster. |
| `count-min-sketch.js` | Estimate the frequency of a given event using the [RedisBloom](https://redisbloom.io) Count-Min Sketch. |
| `cuckoo-filter.js` | Space efficient set membership checks with a [Cuckoo Filter](https://en.wikipedia.org/wiki/Cuckoo_filter) using [RedisBloom](https://redisbloom.io). |
| `dump-and-restore.js` | Demonstrates the use of the [`DUMP`](https://redis.io/commands/dump/) and [`RESTORE`](https://redis.io/commands/restore/) commands |
| `get-server-time.js` | Get the time from the Redis server. |
| `hyperloglog.js` | Showing use of Hyperloglog commands [PFADD, PFCOUNT and PFMERGE](https://redis.io/commands/?group=hyperloglog). |
| `lua-multi-incr.js` | Define a custom lua script that allows you to perform INCRBY on multiple keys. |
Expand Down
22 changes: 22 additions & 0 deletions examples/dump-and-restore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This example demonstrates the use of the DUMP and RESTORE commands

import { commandOptions, createClient } from 'redis';

const client = createClient();
await client.connect();

// DUMP a specific key into a local variable
const dump = await client.dump(
commandOptions({ returnBuffers: true }),
'source'
);

// RESTORE into a new key
await client.restore('destination', 0, dump);

// RESTORE and REPLACE an existing key
await client.restore('destination', 0, dump, {
REPLACE: true
});

await client.quit();
3 changes: 3 additions & 0 deletions packages/client/lib/cluster/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ import * as PTTL from '../commands/PTTL';
import * as PUBLISH from '../commands/PUBLISH';
import * as RENAME from '../commands/RENAME';
import * as RENAMENX from '../commands/RENAMENX';
import * as RESTORE from '../commands/RESTORE';
import * as RPOP_COUNT from '../commands/RPOP_COUNT';
import * as RPOP from '../commands/RPOP';
import * as RPOPLPUSH from '../commands/RPOPLPUSH';
Expand Down Expand Up @@ -434,6 +435,8 @@ export default {
rename: RENAME,
RENAMENX,
renameNX: RENAMENX,
RESTORE,
restore: RESTORE,
RPOP_COUNT,
rPopCount: RPOP_COUNT,
RPOP,
Expand Down
74 changes: 74 additions & 0 deletions packages/client/lib/commands/RESTORE.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './RESTORE';

describe('RESTORE', () => {
describe('transformArguments', () => {
it('simple', () => {
assert.deepEqual(
transformArguments('key', 0, 'value'),
['RESTORE', 'key', '0', 'value']
);
});

it('with REPLACE', () => {
assert.deepEqual(
transformArguments('key', 0, 'value', {
REPLACE: true
}),
['RESTORE', 'key', '0', 'value', 'REPLACE']
);
});

it('with ABSTTL', () => {
assert.deepEqual(
transformArguments('key', 0, 'value', {
ABSTTL: true
}),
['RESTORE', 'key', '0', 'value', 'ABSTTL']
);
});

it('with IDLETIME', () => {
assert.deepEqual(
transformArguments('key', 0, 'value', {
IDLETIME: 1
}),
['RESTORE', 'key', '0', 'value', 'IDLETIME', '1']
);
});

it('with FREQ', () => {
assert.deepEqual(
transformArguments('key', 0, 'value', {
FREQ: 1
}),
['RESTORE', 'key', '0', 'value', 'FREQ', '1']
);
});

it('with REPLACE, ABSTTL, IDLETIME and FREQ', () => {
assert.deepEqual(
transformArguments('key', 0, 'value', {
REPLACE: true,
ABSTTL: true,
IDLETIME: 1,
FREQ: 2
}),
['RESTORE', 'key', '0', 'value', 'REPLACE', 'ABSTTL', 'IDLETIME', '1', 'FREQ', '2']
);
});
});

testUtils.testWithClient('client.restore', async client => {
const [, dump] = await Promise.all([
client.set('source', 'value'),
client.dump(client.commandOptions({ returnBuffers: true }), 'source')
]);

assert.equal(
await client.restore('destination', 0, dump),
'OK'
);
}, GLOBAL.SERVERS.OPEN);
});
39 changes: 39 additions & 0 deletions packages/client/lib/commands/RESTORE.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { RedisCommandArgument, RedisCommandArguments } from '.';

export const FIRST_KEY_INDEX = 1;

interface RestoreOptions {
REPLACE?: true;
ABSTTL?: true;
IDLETIME?: number;
FREQ?: number;
}

export function transformArguments(
key: RedisCommandArgument,
ttl: number,
serializedValue: RedisCommandArgument,
options?: RestoreOptions
): RedisCommandArguments {
const args = ['RESTORE', key, ttl.toString(), serializedValue];

if (options?.REPLACE) {
args.push('REPLACE');
}

if (options?.ABSTTL) {
args.push('ABSTTL');
}

if (options?.IDLETIME) {
args.push('IDLETIME', options.IDLETIME.toString());
}

if (options?.FREQ) {
args.push('FREQ', options.FREQ.toString());
}

return args;
}

export declare function transformReply(): 'OK';