Skip to content

Commit

Permalink
fix #1970 - add support for RESTORE (#2535)
Browse files Browse the repository at this point in the history
* - Added RESTORE functionality

* add FIRST_KEY_INDEX, fix tests, clean example, add example to examples table

* use returnBuffers in test

---------

Co-authored-by: Leibale Eidelman <[email protected]>
  • Loading branch information
Moshe-RS and leibale authored Sep 18, 2023
1 parent 8ecfd3e commit 01ca54e
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 1 deletion.
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';

0 comments on commit 01ca54e

Please sign in to comment.