1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-06 02:15:48 +03:00
This commit is contained in:
Leibale
2023-07-06 10:38:30 -04:00
parent 2a662a367d
commit ab153a8eda
10 changed files with 97 additions and 60 deletions

View File

@@ -1,24 +1,20 @@
// import { RedisCommandArgument, RedisCommandArguments } from '.';
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, SetReply, Command } from '../RESP/types';
// export const IS_READ_ONLY = true;
export type CommandGetKeysAndFlagsRawReply = ArrayReply<TuplesReply<[
key: BlobStringReply,
flags: SetReply<BlobStringReply>
]>>;
// export function transformArguments(args: Array<RedisCommandArgument>): RedisCommandArguments {
// return ['COMMAND', 'GETKEYSANDFLAGS', ...args];
// }
// type KeysAndFlagsRawReply = Array<[
// RedisCommandArgument,
// RedisCommandArguments
// ]>;
// type KeysAndFlagsReply = Array<{
// key: RedisCommandArgument;
// flags: RedisCommandArguments;
// }>;
// export function transformReply(reply: KeysAndFlagsRawReply): KeysAndFlagsReply {
// return reply.map(([key, flags]) => ({
// key,
// flags
// }));
// }
export default {
FIRST_KEY_INDEX: undefined,
IS_READ_ONLY: true,
transformArguments(args: Array<RedisArgument>) {
return ['COMMAND', 'GETKEYSANDFLAGS', ...args];
},
transformReply(reply: CommandGetKeysAndFlagsRawReply) {
return reply.map(([key, flags]) => ({
key,
flags
}));
}
} as const satisfies Command;

View File

@@ -9,7 +9,7 @@ export const MATH_FUNCTION = {
engine: 'LUA',
code:
`#!LUA name=math
redis.register_function{
redis.register_function {
function_name = "square",
callback = function(keys, args) return args[1] * args[1] end,
flags = { "no-writes" }

View File

@@ -18,7 +18,9 @@ describe('MEMORY STATS', () => {
assert.equal(typeof memoryStats['replication.backlog'], 'number');
assert.equal(typeof memoryStats['clients.slaves'], 'number');
assert.equal(typeof memoryStats['clients.normal'], 'number');
assert.equal(typeof memoryStats['cluster.links'], 'number');
if (testUtils.isVersionGreaterThan([7])) {
assert.equal(typeof memoryStats['cluster.links'], 'number');
}
assert.equal(typeof memoryStats['aof.buffer'], 'number');
assert.equal(typeof memoryStats['lua.caches'], 'number');
assert.equal(typeof memoryStats['functions.caches'], 'number');

View File

@@ -7,6 +7,7 @@ export type MemoryStatsReply = TuplesToMapReply<[
[BlobStringReply<'replication.backlog'>, NumberReply],
[BlobStringReply<'clients.slaves'>, NumberReply],
[BlobStringReply<'clients.normal'>, NumberReply],
/** added in 7.0 */
[BlobStringReply<'cluster.links'>, NumberReply],
[BlobStringReply<'aof.buffer'>, NumberReply],
[BlobStringReply<'lua.caches'>, NumberReply],

View File

@@ -15,7 +15,11 @@ describe('XINFO CONSUMERS', () => {
client.xGroupCreate('key', 'group', '$', {
MKSTREAM: true
}),
client.xGroupCreateConsumer('key', 'group', 'consumer'),
// using `XREADGROUP` and not `XGROUP CREATECONSUMER` because the latter was introduced in Redis 6.2
client.xReadGroup('group', 'consumer', {
key: 'key',
id: '0-0'
}),
client.xInfoConsumers('key', 'group')
]);

View File

@@ -25,8 +25,10 @@ describe('XINFO GROUPS', () => {
consumers: 0,
pending: 0,
'last-delivered-id': '0-0',
'entries-read': null,
lag: 0
...testUtils.isVersionGreaterThan([7, 0]) && {
'entries-read': null,
lag: 0
}
}]
);
}, {

View File

@@ -23,9 +23,11 @@ describe('XINFO STREAM', () => {
'radix-tree-keys': 0,
'radix-tree-nodes': 1,
'last-generated-id': '0-0',
'max-deleted-entry-id': '0-0',
'entries-added': 0,
'recorded-first-entry-id': '0-0',
...testUtils.isVersionGreaterThan([7, 0]) && {
'max-deleted-entry-id': '0-0',
'entries-added': 0,
'recorded-first-entry-id': '0-0',
},
groups: 1,
'first-entry': null,
'last-entry': null

View File

@@ -1,26 +1,16 @@
import { TuplesToMapReply, BlobStringReply, NumberReply, NullReply, Resp2Reply, Command, RespType, RESP_TYPES, RedisArgument } from '../RESP/types';
import { StreamMessageRawReply, transformStreamMessageReply } from './generic-transformers';
export type XInfoStreamRawReply = TuplesToMapReply<[
[BlobStringReply<'length'>, NumberReply],
[BlobStringReply<'radix-tree-keys'>, NumberReply],
[BlobStringReply<'radix-tree-nodes'>, NumberReply],
[BlobStringReply<'last-generated-id'>, BlobStringReply],
[BlobStringReply<'max-deleted-entry-id'>, BlobStringReply],
[BlobStringReply<'entries-added'>, NumberReply],
[BlobStringReply<'recorded-first-entry-id'>, BlobStringReply],
[BlobStringReply<'groups'>, NumberReply],
[BlobStringReply<'first-entry'>, StreamMessageRawReply | NullReply],
[BlobStringReply<'last-entry'>, StreamMessageRawReply | NullReply]
]>;
export type XInfoStreamReply = TuplesToMapReply<[
[BlobStringReply<'length'>, NumberReply],
[BlobStringReply<'radix-tree-keys'>, NumberReply],
[BlobStringReply<'radix-tree-nodes'>, NumberReply],
[BlobStringReply<'last-generated-id'>, BlobStringReply],
/** added in 7.2 */
[BlobStringReply<'max-deleted-entry-id'>, BlobStringReply],
/** added in 7.2 */
[BlobStringReply<'entries-added'>, NumberReply],
/** added in 7.2 */
[BlobStringReply<'recorded-first-entry-id'>, BlobStringReply],
[BlobStringReply<'groups'>, NumberReply],
[BlobStringReply<'first-entry'>, ReturnType<typeof transformStreamMessageReply> | NullReply],
@@ -34,22 +24,27 @@ export default {
return ['XINFO', 'STREAM', key];
},
transformReply: {
2(reply: Resp2Reply<XInfoStreamRawReply>) {
return {
length: reply[1],
'radix-tree-keys': reply[3],
'radix-tree-nodes': reply[5],
'last-generated-id': reply[7],
'max-deleted-entry-id': reply[9],
'entries-added': reply[11],
'recorded-first-entry-id': reply[13],
groups: reply[15],
'first-entry': transformEntry(reply[17]),
'last-entry': transformEntry(reply[19])
};
// TODO: is there a "type safe" way to do it?
2(reply: any) {
const parsedReply: Partial<XInfoStreamReply['DEFAULT']> = {};
for (let i = 0; i < reply.length; i += 2) {
switch (reply[i]) {
case 'first-entry':
case 'last-entry':
parsedReply[reply[i] as ('first-entry' | 'last-entry')] = transformEntry(reply[i + 1]) as any;
break;
default:
parsedReply[reply[i] as keyof typeof parsedReply] = reply[i + 1];
break;
}
}
return parsedReply as XInfoStreamReply['DEFAULT'];
},
3(reply: any) { // TODO: is there a "type safe" way to do it?
if (reply instanceof Map) {
3(reply: any) {
if (reply instanceof Map) {
reply.set(
'first-entry',
transformEntry(reply.get('first-entry'))

View File

@@ -41,11 +41,10 @@ describe('XPENDING RANGE', () => {
});
testUtils.testAll('xPendingRange', async client => {
const [, , id, , reply] = await Promise.all([
const [, , id, reply] = await Promise.all([
client.xGroupCreate('key', 'group', '$', {
MKSTREAM: true
}),
client.xGroupCreateConsumer('key', 'group', 'consumer'),
client.xAdd('key', '*', { field: 'value' }),
client.xReadGroup('group', 'consumer', {
key: 'key',

View File

@@ -66,6 +66,12 @@ import CLUSTER_SAVECONFIG from './CLUSTER_SAVECONFIG';
import CLUSTER_SET_CONFIG_EPOCH from './CLUSTER_SET-CONFIG-EPOCH';
import CLUSTER_SETSLOT from './CLUSTER_SETSLOT';
import CLUSTER_SLOTS from './CLUSTER_SLOTS';
import COMMAND_COUNT from './COMMAND_COUNT';
import COMMAND_GETKEYS from './COMMAND_GETKEYS';
import COMMAND_GETKEYSANDFLAGS from './COMMAND_GETKEYSANDFLAGS';
// import COMMAND_INFO from './COMMAND_INFO';
// import COMMAND_LIST from './COMMAND_LIST';
// import COMMAND from './COMMAND';
import CONFIG_GET from './CONFIG_GET';
import CONFIG_RESETASTAT from './CONFIG_RESETSTAT';
import CONFIG_REWRITE from './CONFIG_REWRITE';
@@ -388,6 +394,12 @@ type CLUSTER_SAVECONFIG = typeof import('./CLUSTER_SAVECONFIG').default;
type CLUSTER_SET_CONFIG_EPOCH = typeof import('./CLUSTER_SET-CONFIG-EPOCH').default;
type CLUSTER_SETSLOT = typeof import('./CLUSTER_SETSLOT').default;
type CLUSTER_SLOTS = typeof import('./CLUSTER_SLOTS').default;
type COMMAND_COUNT = typeof import('./COMMAND_COUNT').default;
type COMMAND_GETKEYS = typeof import('./COMMAND_GETKEYS').default;
type COMMAND_GETKEYSANDFLAGS = typeof import('./COMMAND_GETKEYSANDFLAGS').default;
// type COMMAND_INFO = typeof import('./COMMAND_INFO').default;
// type COMMAND_LIST = typeof import('./COMMAND_LIST').default;
// type COMMAND = typeof import('./COMMAND').default;
type CONFIG_GET = typeof import('./CONFIG_GET').default;
type CONFIG_RESETASTAT = typeof import('./CONFIG_RESETSTAT').default;
type CONFIG_REWRITE = typeof import('./CONFIG_REWRITE').default;
@@ -778,6 +790,18 @@ type Commands = {
clusterSetSlot: CLUSTER_SETSLOT;
CLUSTER_SLOTS: CLUSTER_SLOTS;
clusterSlots: CLUSTER_SLOTS;
COMMAND_COUNT: COMMAND_COUNT;
commandCount: COMMAND_COUNT;
COMMAND_GETKEYS: COMMAND_GETKEYS;
commandGetKeys: COMMAND_GETKEYS;
COMMAND_GETKEYSANDFLAGS: COMMAND_GETKEYSANDFLAGS;
commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS;
// COMMAND_INFO: COMMAND_INFO;
// commandInfo: COMMAND_INFO;
// COMMAND_LIST: COMMAND_LIST;
// commandList: COMMAND_LIST;
// COMMAND: COMMAND;
// command: COMMAND;
CONFIG_GET: CONFIG_GET;
configGet: CONFIG_GET;
CONFIG_RESETASTAT: CONFIG_RESETASTAT;
@@ -1423,6 +1447,18 @@ export default {
clusterSetSlot: CLUSTER_SETSLOT,
CLUSTER_SLOTS,
clusterSlots: CLUSTER_SLOTS,
COMMAND_COUNT,
commandCount: COMMAND_COUNT,
COMMAND_GETKEYS,
commandGetKeys: COMMAND_GETKEYS,
COMMAND_GETKEYSANDFLAGS,
commandGetKeysAndFlags: COMMAND_GETKEYSANDFLAGS,
// COMMAND_INFO,
// commandInfo: COMMAND_INFO,
// COMMAND_LIST,
// commandList: COMMAND_LIST,
// COMMAND,
// command: COMMAND,
CONFIG_GET,
configGet: CONFIG_GET,
CONFIG_RESETASTAT,