You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-09 00:22:08 +03:00
Merge branch 'master' of github.com:redis/node-redis into v5
This commit is contained in:
@@ -24,9 +24,5 @@ describe('LATENCY GRAPH', () => {
|
||||
typeof await client.latencyGraph('command'),
|
||||
'string'
|
||||
);
|
||||
}, {
|
||||
serverArguments: testUtils.isVersionGreaterThan([7]) ?
|
||||
['--enable-debug-command', 'yes'] :
|
||||
GLOBAL.SERVERS.OPEN.serverArguments
|
||||
});
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
27
packages/client/lib/commands/LATENCY_LATEST.spec.ts
Normal file
27
packages/client/lib/commands/LATENCY_LATEST.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import {strict as assert} from 'assert';
|
||||
import testUtils, {GLOBAL} from '../test-utils';
|
||||
import { transformArguments } from './LATENCY_LATEST';
|
||||
|
||||
describe('LATENCY LATEST', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(),
|
||||
['LATENCY', 'LATEST']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.latencyLatest', async client => {
|
||||
await Promise.all([
|
||||
client.configSet('latency-monitor-threshold', '100'),
|
||||
client.sendCommand(['DEBUG', 'SLEEP', '1'])
|
||||
]);
|
||||
const latency = await client.latencyLatest();
|
||||
assert.ok(Array.isArray(latency));
|
||||
for (const [name, timestamp, latestLatency, allTimeLatency] of latency) {
|
||||
assert.equal(typeof name, 'string');
|
||||
assert.equal(typeof timestamp, 'number');
|
||||
assert.equal(typeof latestLatency, 'number');
|
||||
assert.equal(typeof allTimeLatency, 'number');
|
||||
}
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
12
packages/client/lib/commands/LATENCY_LATEST.ts
Normal file
12
packages/client/lib/commands/LATENCY_LATEST.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { RedisCommandArguments } from '.';
|
||||
|
||||
export function transformArguments(): RedisCommandArguments {
|
||||
return ['LATENCY', 'LATEST'];
|
||||
}
|
||||
|
||||
export declare function transformReply(): Array<[
|
||||
name: string,
|
||||
timestamp: number,
|
||||
latestLatency: number,
|
||||
allTimeLatency: number
|
||||
]>;
|
@@ -13,17 +13,19 @@
|
||||
// it('transformReply', () => {
|
||||
// assert.deepEqual(
|
||||
// transformReply([
|
||||
// ['name', 'Alice', 'pending', 1, 'idle', 9104628],
|
||||
// ['name', 'Bob', 'pending', 1, 'idle', 83841983]
|
||||
// ['name', 'Alice', 'pending', 1, 'idle', 9104628, 'inactive', 9281221],
|
||||
// ['name', 'Bob', 'pending', 1, 'idle', 83841983, 'inactive', 7213871]
|
||||
// ]),
|
||||
// [{
|
||||
// name: 'Alice',
|
||||
// pending: 1,
|
||||
// idle: 9104628
|
||||
// idle: 9104628,
|
||||
// inactive: 9281221,
|
||||
// }, {
|
||||
// name: 'Bob',
|
||||
// pending: 1,
|
||||
// idle: 83841983
|
||||
// idle: 83841983,
|
||||
// inactive: 7213871,
|
||||
// }]
|
||||
// );
|
||||
// });
|
||||
|
@@ -15,12 +15,14 @@
|
||||
// name: RedisCommandArgument;
|
||||
// pending: number;
|
||||
// idle: number;
|
||||
// inactive: number;
|
||||
// }>;
|
||||
|
||||
// export function transformReply(rawReply: Array<any>): XInfoConsumersReply {
|
||||
// return rawReply.map(consumer => ({
|
||||
// name: consumer[1],
|
||||
// pending: consumer[3],
|
||||
// idle: consumer[5]
|
||||
// idle: consumer[5],
|
||||
// inactive: consumer[7]
|
||||
// }));
|
||||
// }
|
||||
|
@@ -2,18 +2,24 @@ import TestUtils from '@redis/test-utils';
|
||||
import { SinonSpy } from 'sinon';
|
||||
import { promiseTimeout } from './utils';
|
||||
|
||||
export default new TestUtils({
|
||||
dockerImageName: 'redis',
|
||||
dockerImageVersionArgument: 'redis-version'
|
||||
const utils = new TestUtils({
|
||||
dockerImageName: 'redis',
|
||||
dockerImageVersionArgument: 'redis-version'
|
||||
});
|
||||
|
||||
export default utils;
|
||||
|
||||
const DEBUG_MODE_ARGS = utils.isVersionGreaterThan([7]) ?
|
||||
['--enable-debug-command', 'yes'] :
|
||||
[];
|
||||
|
||||
export const GLOBAL = {
|
||||
SERVERS: {
|
||||
OPEN: {
|
||||
serverArguments: []
|
||||
serverArguments: [...DEBUG_MODE_ARGS]
|
||||
},
|
||||
PASSWORD: {
|
||||
serverArguments: ['--requirepass', 'password'],
|
||||
serverArguments: ['--requirepass', 'password', ...DEBUG_MODE_ARGS],
|
||||
clientOptions: {
|
||||
password: 'password'
|
||||
}
|
||||
@@ -21,10 +27,10 @@ export const GLOBAL = {
|
||||
},
|
||||
CLUSTERS: {
|
||||
OPEN: {
|
||||
serverArguments: []
|
||||
serverArguments: [...DEBUG_MODE_ARGS]
|
||||
},
|
||||
PASSWORD: {
|
||||
serverArguments: ['--requirepass', 'password'],
|
||||
serverArguments: ['--requirepass', 'password', ...DEBUG_MODE_ARGS],
|
||||
clusterConfiguration: {
|
||||
defaults: {
|
||||
password: 'password'
|
||||
@@ -32,7 +38,7 @@ export const GLOBAL = {
|
||||
}
|
||||
},
|
||||
WITH_REPLICAS: {
|
||||
serverArguments: [],
|
||||
serverArguments: [...DEBUG_MODE_ARGS],
|
||||
numberOfMasters: 2,
|
||||
numberOfReplicas: 1,
|
||||
clusterConfiguration: {
|
||||
|
@@ -68,7 +68,7 @@ describe('Graph', () => {
|
||||
|
||||
// check with and without metadata cache
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const { data } = await graph.query('CREATE ()-[edge :edge]->() RETURN edge');
|
||||
const { data } = await graph.query<any>('CREATE ()-[edge :edge]->() RETURN edge');
|
||||
assert.ok(Array.isArray(data));
|
||||
assert.equal(data.length, 1);
|
||||
assert.equal(typeof data[0].edge.id, 'number');
|
||||
@@ -85,7 +85,7 @@ describe('Graph', () => {
|
||||
|
||||
// check with and without metadata cache
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const { data } = await graph.query('CREATE (node :node { p: 0 }) RETURN node');
|
||||
const { data } = await graph.query<any>('CREATE (node :node { p: 0 }) RETURN node');
|
||||
assert.ok(Array.isArray(data));
|
||||
assert.equal(data.length, 1);
|
||||
assert.equal(typeof data[0].node.id, 'number');
|
||||
@@ -98,7 +98,7 @@ describe('Graph', () => {
|
||||
const graph = new Graph(client as any, 'graph'),
|
||||
[, { data }] = await Promise.all([
|
||||
await graph.query('CREATE ()-[:edge]->()'),
|
||||
await graph.roQuery('MATCH path = ()-[:edge]->() RETURN path')
|
||||
await graph.roQuery<any>('MATCH path = ()-[:edge]->() RETURN path')
|
||||
]);
|
||||
|
||||
assert.ok(Array.isArray(data));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# @redis/json
|
||||
|
||||
This package provides support for the [RedisJSON](https://redisjson.io) module, which adds JSON as a native data type to Redis. It extends the [Node Redis client](https://github.com/redis/node-redis) to include functions for each of the RedisJSON commands.
|
||||
This package provides support for the [RedisJSON](https://redis.io/docs/stack/json/) module, which adds JSON as a native data type to Redis. It extends the [Node Redis client](https://github.com/redis/node-redis) to include functions for each of the RedisJSON commands.
|
||||
|
||||
To use these extra commands, your Redis server must have the RedisJSON module installed.
|
||||
|
||||
@@ -10,7 +10,7 @@ For a complete example, see [`managing-json.js`](https://github.com/redis/node-r
|
||||
|
||||
### Storing JSON Documents in Redis
|
||||
|
||||
The [`JSON.SET`](https://oss.redis.com/redisjson/commands/#jsonset) command stores a JSON value at a given JSON Path in a Redis key.
|
||||
The [`JSON.SET`](https://redis.io/commands/json.set/) command stores a JSON value at a given JSON Path in a Redis key.
|
||||
|
||||
Here, we'll store a JSON document in the root of the Redis key "`mydoc`":
|
||||
|
||||
@@ -37,11 +37,11 @@ await client.json.set('noderedis:jsondata', '$', {
|
||||
});
|
||||
```
|
||||
|
||||
For more information about RedisJSON's path syntax, [check out the documentation](https://oss.redis.com/redisjson/path/).
|
||||
For more information about RedisJSON's path syntax, [check out the documentation](https://redis.io/docs/stack/json/path/).
|
||||
|
||||
### Retrieving JSON Documents from Redis
|
||||
|
||||
With RedisJSON, we can retrieve all or part(s) of a JSON document using the [`JSON.GET`]() command and one or more JSON Paths. Let's get the name and age of one of the pets:
|
||||
With RedisJSON, we can retrieve all or part(s) of a JSON document using the [`JSON.GET`](https://redis.io/commands/json.get/) command and one or more JSON Paths. Let's get the name and age of one of the pets:
|
||||
|
||||
```javascript
|
||||
const results = await client.json.get('noderedis:jsondata', {
|
||||
@@ -62,19 +62,19 @@ const results = await client.json.get('noderedis:jsondata', {
|
||||
|
||||
RedisJSON includes commands that can atomically update values in a JSON document, in place in Redis without having to first retrieve the entire document.
|
||||
|
||||
Using the [`JSON.NUMINCRBY`](https://oss.redis.com/redisjson/commands/#jsonnumincrby) command, we can update the age of one of the pets like this:
|
||||
Using the [`JSON.NUMINCRBY`](https://redis.io/commands/json.numincrby/) command, we can update the age of one of the pets like this:
|
||||
|
||||
```javascript
|
||||
await client.json.numIncrBy('noderedis:jsondata', '.pets[1].age', 1);
|
||||
```
|
||||
|
||||
And we can add a new object to the pets array with the [`JSON.ARRAPPEND`](https://oss.redis.com/redisjson/commands/#jsonarrappend) command:
|
||||
And we can add a new object to the pets array with the [`JSON.ARRAPPEND`](https://redis.io/commands/json.arrappend/) command:
|
||||
|
||||
```javascript
|
||||
await client.json.arrAppend('noderedis:jsondata', '.pets', {
|
||||
name: 'Robin',
|
||||
species: 'bird',
|
||||
age: 1,
|
||||
isMammal: false
|
||||
});
|
||||
await client.json.arrAppend('noderedis:jsondata', '.pets', {
|
||||
name: 'Robin',
|
||||
species: 'bird',
|
||||
age: 1,
|
||||
isMammal: false
|
||||
});
|
||||
```
|
||||
|
@@ -454,6 +454,13 @@ describe('AGGREGATE', () => {
|
||||
['FT.AGGREGATE', 'index', '*', 'DIALECT', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with TIMEOUT', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('index', '*', { TIMEOUT: 10 }),
|
||||
['FT.AGGREGATE', 'index', '*', 'TIMEOUT', '10']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ft.aggregate', async client => {
|
||||
|
@@ -124,6 +124,7 @@ export interface AggregateOptions {
|
||||
STEPS?: Array<GroupByStep | SortStep | ApplyStep | LimitStep | FilterStep>;
|
||||
PARAMS?: Params;
|
||||
DIALECT?: number;
|
||||
TIMEOUT?: number;
|
||||
}
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
@@ -213,6 +214,10 @@ export function pushAggregatehOptions(
|
||||
args.push('DIALECT', options.DIALECT.toString());
|
||||
}
|
||||
|
||||
if (options?.TIMEOUT !== undefined) {
|
||||
args.push('TIMEOUT', options.TIMEOUT.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
|
@@ -4,15 +4,24 @@ import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './CURSOR_READ';
|
||||
|
||||
describe('CURSOR READ', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('index', 0),
|
||||
['FT.CURSOR', 'READ', 'index', '0']
|
||||
);
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('index', 0),
|
||||
['FT.CURSOR', 'READ', 'index', '0']
|
||||
);
|
||||
});
|
||||
|
||||
it('with COUNT', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('index', 0, { COUNT: 1 }),
|
||||
['FT.CURSOR', 'READ', 'index', '0', 'COUNT', '1']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ft.cursorRead', async client => {
|
||||
const [ ,, { cursor } ] = await Promise.all([
|
||||
const [, , { cursor }] = await Promise.all([
|
||||
client.ft.create('idx', {
|
||||
field: {
|
||||
type: SchemaFieldTypes.TEXT
|
||||
|
@@ -4,16 +4,27 @@ export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
interface CursorReadOptions {
|
||||
COUNT?: number;
|
||||
}
|
||||
|
||||
export function transformArguments(
|
||||
index: RedisCommandArgument,
|
||||
cursor: number
|
||||
cursor: number,
|
||||
options?: CursorReadOptions
|
||||
): RedisCommandArguments {
|
||||
return [
|
||||
const args = [
|
||||
'FT.CURSOR',
|
||||
'READ',
|
||||
index,
|
||||
cursor.toString()
|
||||
];
|
||||
|
||||
if (options?.COUNT) {
|
||||
args.push('COUNT', options.COUNT.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export { transformReply } from './AGGREGATE_WITHCURSOR';
|
||||
|
@@ -233,6 +233,15 @@ describe('SEARCH', () => {
|
||||
['FT.SEARCH', 'index', 'query', 'DIALECT', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with TIMEOUT', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('index', 'query', {
|
||||
TIMEOUT: 5
|
||||
}),
|
||||
['FT.SEARCH', 'index', 'query', 'TIMEOUT', '5']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('client.ft.search', () => {
|
||||
|
@@ -55,6 +55,7 @@ export interface SearchOptions {
|
||||
};
|
||||
PARAMS?: Params;
|
||||
DIALECT?: number;
|
||||
TIMEOUT?: number;
|
||||
}
|
||||
|
||||
export function transformArguments(
|
||||
|
@@ -510,6 +510,10 @@ export function pushSearchOptions(
|
||||
args.preserve = true;
|
||||
}
|
||||
|
||||
if (options?.TIMEOUT !== undefined) {
|
||||
args.push('TIMEOUT', options.TIMEOUT.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@redis/search",
|
||||
"version": "1.1.2",
|
||||
"version": "1.1.3",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
|
Reference in New Issue
Block a user