You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
stream commands + some more
This commit is contained in:
@@ -22,6 +22,7 @@ You can override the default options by providing a configuration object:
|
||||
|
||||
```typescript
|
||||
client.scanIterator({
|
||||
cursor: 0, // 0 by default
|
||||
TYPE: 'string', // `SCAN` only
|
||||
MATCH: 'patter*',
|
||||
COUNT: 100
|
||||
|
15
docs/todo.md
15
docs/todo.md
@@ -1,21 +1,6 @@
|
||||
# Client
|
||||
|
||||
- Does `close`/`destory` actually close the connection from the Redis POV? Works with OSS, but what about Redis Enterprie?
|
||||
|
||||
Docs:
|
||||
- [v4 to v5](./v4-to-v5.md) - Legacy mode
|
||||
- [Command Options](./command-options.md)
|
||||
- [RESP](./RESP.md)
|
||||
|
||||
# Server
|
||||
|
||||
- `HEXISTS`: accepts one field only, should be the same as `EXISTS`
|
||||
|
||||
`String` -> `Double`:
|
||||
- `INCRBYFLOAT`
|
||||
- `HINCRBYFLOAT`
|
||||
- `GEODIST`
|
||||
|
||||
`Number` -> `Boolean`:
|
||||
- `HSETNX` (deprecated)
|
||||
- `SCRIPT EXISTS`
|
||||
|
@@ -169,6 +169,11 @@ Some command arguments/replies have changed to align more closely to data types
|
||||
- `CLUSTER LINKS`: `createTime` -> `create-time`, `sendBufferAllocated` -> `send-buffer-allocated`, `sendBufferUsed` -> `send-buffer-used` [^map-keys]
|
||||
- `TIME`: `Date` -> `[unixTimestamp: string, microseconds: string]`
|
||||
- `ZMPOP`: `{ elements: Array<{ member: string; score: number; }>; }` -> `{ members: Array<{ value: string; score: number; }>; }` to match other sorted set commands (e.g. `ZRANGE`, `ZSCAN`)
|
||||
- `XGROUP_CREATECONSUMER`: [^boolean-to-number]
|
||||
- `XGROUP_DESTROY`: [^boolean-to-number]
|
||||
- `XINFO GROUPS`: `lastDeliveredId` -> `last-delivered-id` [^map-keys]
|
||||
- `XINFO STREAM`: `radixTreeKeys` -> `radix-tree-keys`, `radixTreeNodes` -> `radix-tree-nodes`, `lastGeneratedId` -> `last-generated-id`, `maxDeletedEntryId` -> `max-deleted-entry-id`, `entriesAdded` -> `entries-added`, `recordedFirstEntryId` -> `recorded-first-entry-id`, `firstEntry` -> `first-entry`, `lastEntry` -> `last-entry`
|
||||
- `XAUTOCLAIM`, `XCLAIM`, `XRANGE`, `XREVRANGE`: `Array<{ name: string; messages: Array<{ id: string; message: Record<string, string> }>; }>` -> `Record<string, Array<{ id: string; message: Record<string, string> }>>`
|
||||
|
||||
[^enum-to-constants]: TODO
|
||||
|
||||
|
@@ -6,7 +6,7 @@ export type RESP_TYPES = typeof RESP_TYPES;
|
||||
|
||||
export type RespTypes = RESP_TYPES[keyof RESP_TYPES];
|
||||
|
||||
type RespType<
|
||||
export type RespType<
|
||||
RESP_TYPE extends RespTypes,
|
||||
DEFAULT,
|
||||
TYPES = never,
|
||||
|
@@ -13,11 +13,11 @@ export default {
|
||||
) {
|
||||
const args = ['BITPOS', key, bit.toString()];
|
||||
|
||||
if (typeof start === 'number') {
|
||||
if (start !== undefined) {
|
||||
args.push(start.toString());
|
||||
}
|
||||
|
||||
if (typeof end === 'number') {
|
||||
if (end !== undefined) {
|
||||
args.push(end.toString());
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,9 @@ describe('LASTSAVE', () => {
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.lastSave', async client => {
|
||||
assert.ok(typeof await client.lastSave() === 'number');
|
||||
assert.equal(
|
||||
typeof await client.lastSave(),
|
||||
'number'
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -12,13 +12,13 @@ export default {
|
||||
) {
|
||||
const args = ['LPOS', key, element];
|
||||
|
||||
if (typeof options?.RANK === 'number') {
|
||||
if (options?.RANK !== undefined) {
|
||||
args.push('RANK', options.RANK.toString());
|
||||
}
|
||||
|
||||
args.push('COUNT', count.toString());
|
||||
|
||||
if (typeof options?.MAXLEN === 'number') {
|
||||
if (options?.MAXLEN !== undefined) {
|
||||
args.push('MAXLEN', options.MAXLEN.toString());
|
||||
}
|
||||
|
||||
|
@@ -1,12 +1,9 @@
|
||||
import { RedisArgument, NumberReply, Command } from '../RESP/types';
|
||||
import { pushVariadicArguments } from './generic-transformers';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
members: Array<RedisArgument> | RedisArgument
|
||||
) {
|
||||
transformArguments(key: RedisArgument, members: RedisVariadicArgument) {
|
||||
return pushVariadicArguments(['SADD', key], members);
|
||||
},
|
||||
transformReply: undefined as unknown as () => NumberReply
|
||||
|
@@ -1,12 +1,10 @@
|
||||
import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types';
|
||||
import { pushVariadicArguments } from './generic-transformers';
|
||||
import { ArrayReply, BlobStringReply, Command } from '../RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(
|
||||
keys: Array<RedisArgument> | RedisArgument
|
||||
) {
|
||||
transformArguments(keys: RedisVariadicArgument) {
|
||||
return pushVariadicArguments(['SDIFF'], keys);
|
||||
},
|
||||
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
|
||||
|
@@ -1,12 +1,9 @@
|
||||
import { RedisArgument, NumberReply, Command } from '../RESP/types';
|
||||
import { pushVariadicArguments } from './generic-transformers';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
transformArguments(
|
||||
destination: RedisArgument,
|
||||
keys: Array<RedisArgument> | RedisArgument
|
||||
) {
|
||||
transformArguments(destination: RedisArgument, keys: RedisVariadicArgument) {
|
||||
return pushVariadicArguments(['SDIFFSTORE', destination], keys);
|
||||
},
|
||||
transformReply: undefined as unknown as () => NumberReply
|
||||
|
@@ -1,12 +1,10 @@
|
||||
import { RedisArgument, ArrayReply, BlobStringReply, Command } from '../RESP/types';
|
||||
import { pushVariadicArguments } from './generic-transformers';
|
||||
import { ArrayReply, BlobStringReply, Command } from '../RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from './generic-transformers';
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(
|
||||
keys: Array<RedisArgument> | RedisArgument
|
||||
) {
|
||||
transformArguments(keys: RedisVariadicArgument) {
|
||||
return pushVariadicArguments(['SINTER'], keys);
|
||||
},
|
||||
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { RedisArgument, NumberReply, Command } from '../RESP/types';
|
||||
import { pushVariadicArgument } from './generic-transformers';
|
||||
import { NumberReply, Command } from '../RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArgument } from './generic-transformers';
|
||||
|
||||
export interface SInterCardOptions {
|
||||
LIMIT?: number;
|
||||
@@ -9,7 +9,7 @@ export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(
|
||||
keys: Array<RedisArgument> | RedisArgument,
|
||||
keys: RedisVariadicArgument,
|
||||
options?: SInterCardOptions | number // `number` for backwards compatibility
|
||||
) {
|
||||
const args = pushVariadicArgument(['SINTERCARD'], keys);
|
||||
|
@@ -6,22 +6,22 @@ describe('XACK', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('string', () => {
|
||||
assert.deepEqual(
|
||||
XACK.transformArguments('key', 'group', '1-0'),
|
||||
['XACK', 'key', 'group', '1-0']
|
||||
XACK.transformArguments('key', 'group', '0-0'),
|
||||
['XACK', 'key', 'group', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
it('array', () => {
|
||||
assert.deepEqual(
|
||||
XACK.transformArguments('key', 'group', ['1-0', '2-0']),
|
||||
['XACK', 'key', 'group', '1-0', '2-0']
|
||||
XACK.transformArguments('key', 'group', ['0-0', '1-0']),
|
||||
['XACK', 'key', 'group', '0-0', '1-0']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testAll('xAck', async client => {
|
||||
assert.equal(
|
||||
await client.xAck('key', 'group', '1-0'),
|
||||
await client.xAck('key', 'group', '0-0'),
|
||||
0
|
||||
);
|
||||
}, {
|
||||
|
@@ -1,39 +1,47 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
// import { StreamMessagesReply, transformStreamMessagesReply } from './generic-transformers';
|
||||
import { RedisArgument, TuplesReply, BlobStringReply, ArrayReply, Command } from '../RESP/types';
|
||||
import { StreamMessagesRawReply, transformStreamMessagesReply } from './generic-transformers';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 1;
|
||||
export interface XAutoClaimOptions {
|
||||
COUNT?: number;
|
||||
}
|
||||
|
||||
// export interface XAutoClaimOptions {
|
||||
// COUNT?: number;
|
||||
// }
|
||||
export type XAutoClaimRawReply = TuplesReply<[
|
||||
nextId: BlobStringReply,
|
||||
messages: StreamMessagesRawReply,
|
||||
deletedMessages: ArrayReply<BlobStringReply>
|
||||
]>;
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// group: RedisCommandArgument,
|
||||
// consumer: RedisCommandArgument,
|
||||
// minIdleTime: number,
|
||||
// start: string,
|
||||
// options?: XAutoClaimOptions
|
||||
// ): RedisCommandArguments {
|
||||
// const args = ['XAUTOCLAIM', key, group, consumer, minIdleTime.toString(), start];
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
IS_READ_ONLY: false,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument,
|
||||
consumer: RedisArgument,
|
||||
minIdleTime: number,
|
||||
start: RedisArgument,
|
||||
options?: XAutoClaimOptions
|
||||
) {
|
||||
const args = [
|
||||
'XAUTOCLAIM',
|
||||
key,
|
||||
group,
|
||||
consumer,
|
||||
minIdleTime.toString(),
|
||||
start
|
||||
];
|
||||
|
||||
// if (options?.COUNT) {
|
||||
// args.push('COUNT', options.COUNT.toString());
|
||||
// }
|
||||
if (options?.COUNT) {
|
||||
args.push('COUNT', options.COUNT.toString());
|
||||
}
|
||||
|
||||
// return args;
|
||||
// }
|
||||
|
||||
// type XAutoClaimRawReply = [RedisCommandArgument, Array<any>];
|
||||
|
||||
// interface XAutoClaimReply {
|
||||
// nextId: RedisCommandArgument;
|
||||
// messages: StreamMessagesReply;
|
||||
// }
|
||||
|
||||
// export function transformReply(reply: XAutoClaimRawReply): XAutoClaimReply {
|
||||
// return {
|
||||
// nextId: reply[0],
|
||||
// messages: transformStreamMessagesReply(reply[1])
|
||||
// };
|
||||
// }
|
||||
return args;
|
||||
},
|
||||
transformReply(reply: XAutoClaimRawReply) {
|
||||
return {
|
||||
nextId: reply[0],
|
||||
messages: transformStreamMessagesReply(reply[1]),
|
||||
deletedMessages: reply[2]
|
||||
};
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,25 +1,25 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
// import { transformArguments as transformXAutoClaimArguments } from './XAUTOCLAIM';
|
||||
import { TuplesReply, BlobStringReply, ArrayReply, Command } from '../RESP/types';
|
||||
import XAUTOCLAIM from './XAUTOCLAIM';
|
||||
|
||||
// export { FIRST_KEY_INDEX } from './XAUTOCLAIM';
|
||||
type XAutoClaimJustIdRawReply = TuplesReply<[
|
||||
nextId: BlobStringReply,
|
||||
messages: ArrayReply<BlobStringReply>,
|
||||
deletedMessages: ArrayReply<BlobStringReply>
|
||||
]>;
|
||||
|
||||
// export function transformArguments(...args: Parameters<typeof transformXAutoClaimArguments>): RedisCommandArguments {
|
||||
// return [
|
||||
// ...transformXAutoClaimArguments(...args),
|
||||
// 'JUSTID'
|
||||
// ];
|
||||
// }
|
||||
|
||||
// type XAutoClaimJustIdRawReply = [RedisCommandArgument, Array<RedisCommandArgument>];
|
||||
|
||||
// interface XAutoClaimJustIdReply {
|
||||
// nextId: RedisCommandArgument;
|
||||
// messages: Array<RedisCommandArgument>;
|
||||
// }
|
||||
|
||||
// export function transformReply(reply: XAutoClaimJustIdRawReply): XAutoClaimJustIdReply {
|
||||
// return {
|
||||
// nextId: reply[0],
|
||||
// messages: reply[1]
|
||||
// };
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX: XAUTOCLAIM.FIRST_KEY_INDEX,
|
||||
IS_READ_ONLY: XAUTOCLAIM.IS_READ_ONLY,
|
||||
transformArguments(...args: Parameters<typeof XAUTOCLAIM.transformArguments>) {
|
||||
const redisArgs = XAUTOCLAIM.transformArguments(...args);
|
||||
redisArgs.push('JUSTID');
|
||||
return redisArgs;
|
||||
},
|
||||
transformReply(reply: XAutoClaimJustIdRawReply) {
|
||||
return {
|
||||
nextId: reply[0],
|
||||
messages: reply[1],
|
||||
deletedMessages: reply[2]
|
||||
};
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,90 +1,106 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XCLAIM';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XCLAIM from './XCLAIM';
|
||||
|
||||
// describe('XCLAIM', () => {
|
||||
// describe('transformArguments', () => {
|
||||
// it('single id (string)', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, '0-0'),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0']
|
||||
// );
|
||||
// });
|
||||
describe('XCLAIM', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('single id (string)', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0'),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
// it('multiple ids (array)', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, ['0-0', '1-0']),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', '1-0']
|
||||
// );
|
||||
// });
|
||||
it('multiple ids (array)', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, ['0-0', '1-0']),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', '1-0']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with IDLE', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
// IDLE: 1
|
||||
// }),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1']
|
||||
// );
|
||||
// });
|
||||
it('with IDLE', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
IDLE: 1
|
||||
}),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with TIME (number)', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
// TIME: 1
|
||||
// }),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', '1']
|
||||
// );
|
||||
// });
|
||||
describe('with TIME', () => {
|
||||
it('number', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
TIME: 1
|
||||
}),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', '1']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with TIME (date)', () => {
|
||||
// const d = new Date();
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
// TIME: d
|
||||
// }),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', d.getTime().toString()]
|
||||
// );
|
||||
// });
|
||||
it('Date', () => {
|
||||
const d = new Date();
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
TIME: d
|
||||
}),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'TIME', d.getTime().toString()]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// it('with RETRYCOUNT', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
// RETRYCOUNT: 1
|
||||
// }),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'RETRYCOUNT', '1']
|
||||
// );
|
||||
// });
|
||||
it('with RETRYCOUNT', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
RETRYCOUNT: 1
|
||||
}),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'RETRYCOUNT', '1']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with FORCE', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
// FORCE: true
|
||||
// }),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'FORCE']
|
||||
// );
|
||||
// });
|
||||
it('with FORCE', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
FORCE: true
|
||||
}),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'FORCE']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with IDLE, TIME, RETRYCOUNT, FORCE, JUSTID', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
// IDLE: 1,
|
||||
// TIME: 1,
|
||||
// RETRYCOUNT: 1,
|
||||
// FORCE: true
|
||||
// }),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1', 'TIME', '1', 'RETRYCOUNT', '1', 'FORCE']
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
it('with LASTID', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
LASTID: '0-0'
|
||||
}),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'LASTID', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xClaim', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
it('with IDLE, TIME, RETRYCOUNT, FORCE, LASTID', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM.transformArguments('key', 'group', 'consumer', 1, '0-0', {
|
||||
IDLE: 1,
|
||||
TIME: 1,
|
||||
RETRYCOUNT: 1,
|
||||
FORCE: true,
|
||||
LASTID: '0-0'
|
||||
}),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'IDLE', '1', 'TIME', '1', 'RETRYCOUNT', '1', 'FORCE', 'LASTID', '0-0']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// assert.deepEqual(
|
||||
// await client.xClaim('key', 'group', 'consumer', 1, '0-0'),
|
||||
// []
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
// TODO: test with messages
|
||||
testUtils.testAll('xClaim', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xClaim('key', 'group', 'consumer', 1, '0-0')
|
||||
]);
|
||||
|
||||
assert.deepEqual(reply, []);
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,48 +1,54 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
// import { pushVariadicArguments } from './generic-transformers';
|
||||
import { RedisArgument, Command } from '../RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments, transformStreamMessagesReply } from './generic-transformers';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 1;
|
||||
export interface XClaimOptions {
|
||||
IDLE?: number;
|
||||
TIME?: number | Date;
|
||||
RETRYCOUNT?: number;
|
||||
FORCE?: boolean;
|
||||
LASTID?: RedisArgument;
|
||||
}
|
||||
|
||||
// export interface XClaimOptions {
|
||||
// IDLE?: number;
|
||||
// TIME?: number | Date;
|
||||
// RETRYCOUNT?: number;
|
||||
// FORCE?: true;
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
IS_READ_ONLY: false,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument,
|
||||
consumer: RedisArgument,
|
||||
minIdleTime: number,
|
||||
id: RedisVariadicArgument,
|
||||
options?: XClaimOptions
|
||||
) {
|
||||
const args = pushVariadicArguments(
|
||||
['XCLAIM', key, group, consumer, minIdleTime.toString()],
|
||||
id
|
||||
);
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// group: RedisCommandArgument,
|
||||
// consumer: RedisCommandArgument,
|
||||
// minIdleTime: number,
|
||||
// id: RedisCommandArgument | Array<RedisCommandArgument>,
|
||||
// options?: XClaimOptions
|
||||
// ): RedisCommandArguments {
|
||||
// const args = pushVariadicArguments(
|
||||
// ['XCLAIM', key, group, consumer, minIdleTime.toString()],
|
||||
// id
|
||||
// );
|
||||
if (options?.IDLE !== undefined) {
|
||||
args.push('IDLE', options.IDLE.toString());
|
||||
}
|
||||
|
||||
// if (options?.IDLE) {
|
||||
// args.push('IDLE', options.IDLE.toString());
|
||||
// }
|
||||
if (options?.TIME !== undefined) {
|
||||
args.push(
|
||||
'TIME',
|
||||
(options.TIME instanceof Date ? options.TIME.getTime() : options.TIME).toString()
|
||||
);
|
||||
}
|
||||
|
||||
// if (options?.TIME) {
|
||||
// args.push(
|
||||
// 'TIME',
|
||||
// (typeof options.TIME === 'number' ? options.TIME : options.TIME.getTime()).toString()
|
||||
// );
|
||||
// }
|
||||
if (options?.RETRYCOUNT !== undefined) {
|
||||
args.push('RETRYCOUNT', options.RETRYCOUNT.toString());
|
||||
}
|
||||
|
||||
// if (options?.RETRYCOUNT) {
|
||||
// args.push('RETRYCOUNT', options.RETRYCOUNT.toString());
|
||||
// }
|
||||
if (options?.FORCE) {
|
||||
args.push('FORCE');
|
||||
}
|
||||
|
||||
// if (options?.FORCE) {
|
||||
// args.push('FORCE');
|
||||
// }
|
||||
if (options?.LASTID !== undefined) {
|
||||
args.push('LASTID', options.LASTID);
|
||||
}
|
||||
|
||||
// return args;
|
||||
// }
|
||||
|
||||
// export { transformStreamMessagesReply as transformReply } from './generic-transformers';
|
||||
return args;
|
||||
},
|
||||
transformReply: transformStreamMessagesReply
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,23 +1,24 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XCLAIM_JUSTID';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XCLAIM_JUSTID from './XCLAIM_JUSTID';
|
||||
|
||||
// describe('XCLAIM JUSTID', () => {
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer', 1, '0-0'),
|
||||
// ['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID']
|
||||
// );
|
||||
// });
|
||||
describe('XCLAIM JUSTID', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XCLAIM_JUSTID.transformArguments('key', 'group', 'consumer', 1, '0-0'),
|
||||
['XCLAIM', 'key', 'group', 'consumer', '1', '0-0', 'JUSTID']
|
||||
);
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xClaimJustId', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
// TODO: test with messages
|
||||
testUtils.testWithClient('client.xClaimJustId', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xClaimJustId('key', 'group', 'consumer', 1, '0-0')
|
||||
]);
|
||||
|
||||
// assert.deepEqual(
|
||||
// await client.xClaimJustId('key', 'group', 'consumer', 1, '0-0'),
|
||||
// []
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
assert.deepEqual(reply, []);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,13 +1,13 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
// import { transformArguments as transformXClaimArguments } from './XCLAIM';
|
||||
import { ArrayReply, BlobStringReply, Command } from '../RESP/types';
|
||||
import XCLAIM from './XCLAIM';
|
||||
|
||||
// export { FIRST_KEY_INDEX } from './XCLAIM';
|
||||
|
||||
// export function transformArguments(...args: Parameters<typeof transformXClaimArguments>): RedisCommandArguments {
|
||||
// return [
|
||||
// ...transformXClaimArguments(...args),
|
||||
// 'JUSTID'
|
||||
// ];
|
||||
// }
|
||||
|
||||
// export declare function transformReply(): Array<RedisCommandArgument>;
|
||||
export default {
|
||||
FIRST_KEY_INDEX: XCLAIM.FIRST_KEY_INDEX,
|
||||
IS_READ_ONLY: XCLAIM.IS_READ_ONLY,
|
||||
transformArguments(...args: Parameters<typeof XCLAIM.transformArguments>) {
|
||||
const redisArgs = XCLAIM.transformArguments(...args);
|
||||
redisArgs.push('JUSTID');
|
||||
return redisArgs;
|
||||
},
|
||||
transformReply: undefined as unknown as () => ArrayReply<BlobStringReply>
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,32 +1,44 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XGROUP_CREATE';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './XGROUP_CREATE';
|
||||
|
||||
// describe('XGROUP CREATE', () => {
|
||||
// describe('transformArguments', () => {
|
||||
// it('simple', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', '$'),
|
||||
// ['XGROUP', 'CREATE', 'key', 'group', '$']
|
||||
// );
|
||||
// });
|
||||
describe('XGROUP CREATE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 'group', '$'),
|
||||
['XGROUP', 'CREATE', 'key', 'group', '$']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with MKSTREAM', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// }),
|
||||
// ['XGROUP', 'CREATE', 'key', 'group', '$', 'MKSTREAM']
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
it('with MKSTREAM', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
['XGROUP', 'CREATE', 'key', 'group', '$', 'MKSTREAM']
|
||||
);
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xGroupCreate', async client => {
|
||||
// assert.equal(
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// }),
|
||||
// 'OK'
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
it('with ENTRIESREAD', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', 'group', '$', {
|
||||
ENTRIESREAD: 1
|
||||
}),
|
||||
['XGROUP', 'CREATE', 'key', 'group', '$', 'ENTRIESREAD', '1']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testAll('xGroupCreate', async client => {
|
||||
assert.equal(
|
||||
await client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
'OK'
|
||||
);
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.SERVERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,24 +1,34 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 2;
|
||||
export interface XGroupCreateOptions {
|
||||
MKSTREAM?: boolean;
|
||||
/**
|
||||
* added in 7.0
|
||||
*/
|
||||
ENTRIESREAD?: number;
|
||||
}
|
||||
|
||||
// interface XGroupCreateOptions {
|
||||
// MKSTREAM?: true;
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: false,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument,
|
||||
id: RedisArgument,
|
||||
options?: XGroupCreateOptions
|
||||
) {
|
||||
const args = ['XGROUP', 'CREATE', key, group, id];
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// group: RedisCommandArgument,
|
||||
// id: RedisCommandArgument,
|
||||
// options?: XGroupCreateOptions
|
||||
// ): RedisCommandArguments {
|
||||
// const args = ['XGROUP', 'CREATE', key, group, id];
|
||||
if (options?.MKSTREAM) {
|
||||
args.push('MKSTREAM');
|
||||
}
|
||||
|
||||
// if (options?.MKSTREAM) {
|
||||
// args.push('MKSTREAM');
|
||||
// }
|
||||
if (options?.ENTRIESREAD) {
|
||||
args.push('ENTRIESREAD', options.ENTRIESREAD.toString());
|
||||
}
|
||||
|
||||
// return args;
|
||||
// }
|
||||
return args;
|
||||
},
|
||||
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
|
||||
} as const satisfies Command;
|
||||
|
||||
// export declare function transformReply(): RedisCommandArgument;
|
||||
|
@@ -1,25 +1,28 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XGROUP_CREATECONSUMER';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XGROUP_CREATECONSUMER from './XGROUP_CREATECONSUMER';
|
||||
|
||||
// describe('XGROUP CREATECONSUMER', () => {
|
||||
// testUtils.isVersionGreaterThanHook([6, 2]);
|
||||
describe('XGROUP CREATECONSUMER', () => {
|
||||
testUtils.isVersionGreaterThanHook([6, 2]);
|
||||
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer'),
|
||||
// ['XGROUP', 'CREATECONSUMER', 'key', 'group', 'consumer']
|
||||
// );
|
||||
// });
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XGROUP_CREATECONSUMER.transformArguments('key', 'group', 'consumer'),
|
||||
['XGROUP', 'CREATECONSUMER', 'key', 'group', 'consumer']
|
||||
);
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xGroupCreateConsumer', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
testUtils.testAll('xGroupCreateConsumer', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xGroupCreateConsumer('key', 'group', 'consumer')
|
||||
]);
|
||||
|
||||
// assert.equal(
|
||||
// await client.xGroupCreateConsumer('key', 'group', 'consumer'),
|
||||
// true
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
assert.equal(reply, 1);
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,13 +1,14 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { RedisArgument, Command, NumberReply } from '../RESP/types';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 2;
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// group: RedisCommandArgument,
|
||||
// consumer: RedisCommandArgument
|
||||
// ): RedisCommandArguments {
|
||||
// return ['XGROUP', 'CREATECONSUMER', key, group, consumer];
|
||||
// }
|
||||
|
||||
// export { transformBooleanReply as transformReply } from './generic-transformers';
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: false,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument,
|
||||
consumer: RedisArgument
|
||||
) {
|
||||
return ['XGROUP', 'CREATECONSUMER', key, group, consumer];
|
||||
},
|
||||
transformReply: undefined as unknown as () => NumberReply
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,23 +1,26 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XGROUP_DELCONSUMER';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XGROUP_DELCONSUMER from './XGROUP_DELCONSUMER';
|
||||
|
||||
// describe('XGROUP DELCONSUMER', () => {
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', 'consumer'),
|
||||
// ['XGROUP', 'DELCONSUMER', 'key', 'group', 'consumer']
|
||||
// );
|
||||
// });
|
||||
describe('XGROUP DELCONSUMER', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XGROUP_DELCONSUMER.transformArguments('key', 'group', 'consumer'),
|
||||
['XGROUP', 'DELCONSUMER', 'key', 'group', 'consumer']
|
||||
);
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xGroupDelConsumer', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
testUtils.testAll('xGroupDelConsumer', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xGroupDelConsumer('key', 'group', 'consumer')
|
||||
]);
|
||||
|
||||
// assert.equal(
|
||||
// await client.xGroupDelConsumer('key', 'group', 'consumer'),
|
||||
// 0
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
assert.equal(reply, 0);
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -11,3 +11,18 @@
|
||||
// }
|
||||
|
||||
// export declare function transformReply(): number;
|
||||
|
||||
import { RedisArgument, NumberReply, Command } from '../RESP/types';
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: false,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument,
|
||||
consumer: RedisArgument
|
||||
) {
|
||||
return ['XGROUP', 'DELCONSUMER', key, group, consumer];
|
||||
},
|
||||
transformReply: undefined as unknown as () => NumberReply
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,23 +1,26 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XGROUP_DESTROY';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XGROUP_DESTROY from './XGROUP_DESTROY';
|
||||
|
||||
// describe('XGROUP DESTROY', () => {
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group'),
|
||||
// ['XGROUP', 'DESTROY', 'key', 'group']
|
||||
// );
|
||||
// });
|
||||
describe('XGROUP DESTROY', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XGROUP_DESTROY.transformArguments('key', 'group'),
|
||||
['XGROUP', 'DESTROY', 'key', 'group']
|
||||
);
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xGroupDestroy', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
testUtils.testAll('xGroupDestroy', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xGroupDestroy('key', 'group')
|
||||
]);
|
||||
|
||||
// assert.equal(
|
||||
// await client.xGroupDestroy('key', 'group'),
|
||||
// true
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
assert.equal(reply, 1);
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,12 +1,13 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { RedisArgument, NumberReply, Command } from '../RESP/types';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 2;
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// group: RedisCommandArgument
|
||||
// ): RedisCommandArguments {
|
||||
// return ['XGROUP', 'DESTROY', key, group];
|
||||
// }
|
||||
|
||||
// export { transformBooleanReply as transformReply } from './generic-transformers';
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: false,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument
|
||||
) {
|
||||
return ['XGROUP', 'DESTROY', key, group];
|
||||
},
|
||||
transformReply: undefined as unknown as () => NumberReply
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,23 +1,26 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XGROUP_SETID';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XGROUP_SETID from './XGROUP_SETID';
|
||||
|
||||
// describe('XGROUP SETID', () => {
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', '0'),
|
||||
// ['XGROUP', 'SETID', 'key', 'group', '0']
|
||||
// );
|
||||
// });
|
||||
describe('XGROUP SETID', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XGROUP_SETID.transformArguments('key', 'group', '0'),
|
||||
['XGROUP', 'SETID', 'key', 'group', '0']
|
||||
);
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xGroupSetId', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
testUtils.testAll('xGroupSetId', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xGroupSetId('key', 'group', '0')
|
||||
]);
|
||||
|
||||
// assert.equal(
|
||||
// await client.xGroupSetId('key', 'group', '0'),
|
||||
// 'OK'
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
assert.equal(reply, 'OK');
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,13 +1,26 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 2;
|
||||
export interface XGroupSetIdOptions {
|
||||
/** added in 7.0 */
|
||||
ENTRIESREAD?: number;
|
||||
}
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// group: RedisCommandArgument,
|
||||
// id: RedisCommandArgument
|
||||
// ): RedisCommandArguments {
|
||||
// return ['XGROUP', 'SETID', key, group, id];
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: false,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument,
|
||||
id: RedisArgument,
|
||||
options?: XGroupSetIdOptions
|
||||
) {
|
||||
const args = ['XGROUP', 'SETID', key, group, id];
|
||||
|
||||
// export declare function transformReply(): RedisCommandArgument;
|
||||
if (options?.ENTRIESREAD) {
|
||||
args.push('ENTRIESREAD', options.ENTRIESREAD.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
},
|
||||
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,43 +1,34 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments, transformReply } from './XINFO_CONSUMERS';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XINFO_CONSUMERS from './XINFO_CONSUMERS';
|
||||
|
||||
// describe('XINFO CONSUMERS', () => {
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group'),
|
||||
// ['XINFO', 'CONSUMERS', 'key', 'group']
|
||||
// );
|
||||
// });
|
||||
describe('XINFO CONSUMERS', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XINFO_CONSUMERS.transformArguments('key', 'group'),
|
||||
['XINFO', 'CONSUMERS', 'key', 'group']
|
||||
);
|
||||
});
|
||||
|
||||
// it('transformReply', () => {
|
||||
// assert.deepEqual(
|
||||
// transformReply([
|
||||
// ['name', 'Alice', 'pending', 1, 'idle', 9104628, 'inactive', 9281221],
|
||||
// ['name', 'Bob', 'pending', 1, 'idle', 83841983, 'inactive', 7213871]
|
||||
// ]),
|
||||
// [{
|
||||
// name: 'Alice',
|
||||
// pending: 1,
|
||||
// idle: 9104628,
|
||||
// inactive: 9281221,
|
||||
// }, {
|
||||
// name: 'Bob',
|
||||
// pending: 1,
|
||||
// idle: 83841983,
|
||||
// inactive: 7213871,
|
||||
// }]
|
||||
// );
|
||||
// });
|
||||
testUtils.testAll('xInfoConsumers', async client => {
|
||||
const [, , reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xGroupCreateConsumer('key', 'group', 'consumer'),
|
||||
client.xInfoConsumers('key', 'group')
|
||||
]);
|
||||
|
||||
// testUtils.testWithClient('client.xInfoConsumers', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
|
||||
// assert.deepEqual(
|
||||
// await client.xInfoConsumers('key', 'group'),
|
||||
// []
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
for (const consumer of reply) {
|
||||
assert.equal(typeof consumer.name, 'string');
|
||||
assert.equal(typeof consumer.pending, 'number');
|
||||
assert.equal(typeof consumer.idle, 'number');
|
||||
if (testUtils.isVersionGreaterThan([7, 2])) {
|
||||
assert.equal(typeof consumer.inactive, 'number');
|
||||
}
|
||||
}
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,28 +1,31 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command } from '../RESP/types';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 2;
|
||||
export type XInfoConsumersReply = ArrayReply<TuplesToMapReply<[
|
||||
[BlobStringReply<'name'>, BlobStringReply],
|
||||
[BlobStringReply<'pending'>, NumberReply],
|
||||
[BlobStringReply<'idle'>, NumberReply],
|
||||
/** added in 7.2 */
|
||||
[BlobStringReply<'inactive'>, NumberReply]
|
||||
]>>;
|
||||
|
||||
// export const IS_READ_ONLY = true;
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// group: RedisCommandArgument
|
||||
// ): RedisCommandArguments {
|
||||
// return ['XINFO', 'CONSUMERS', key, group];
|
||||
// }
|
||||
|
||||
// type XInfoConsumersReply = Array<{
|
||||
// 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],
|
||||
// inactive: consumer[7]
|
||||
// }));
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument
|
||||
) {
|
||||
return ['XINFO', 'CONSUMERS', key, group];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<XInfoConsumersReply>) => {
|
||||
return reply.map(consumer => ({
|
||||
name: consumer[1],
|
||||
pending: consumer[3],
|
||||
idle: consumer[5],
|
||||
inactive: consumer[7]
|
||||
}));
|
||||
},
|
||||
3: undefined as unknown as () => XInfoConsumersReply
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,48 +1,36 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments, transformReply } from './XINFO_GROUPS';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XINFO_GROUPS from './XINFO_GROUPS';
|
||||
|
||||
// describe('XINFO GROUPS', () => {
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key'),
|
||||
// ['XINFO', 'GROUPS', 'key']
|
||||
// );
|
||||
// });
|
||||
describe('XINFO GROUPS', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XINFO_GROUPS.transformArguments('key'),
|
||||
['XINFO', 'GROUPS', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
// it('transformReply', () => {
|
||||
// assert.deepEqual(
|
||||
// transformReply([
|
||||
// ['name', 'mygroup', 'consumers', 2, 'pending', 2, 'last-delivered-id', '1588152489012-0'],
|
||||
// ['name', 'some-other-group', 'consumers', 1, 'pending', 0, 'last-delivered-id', '1588152498034-0']
|
||||
// ]),
|
||||
// [{
|
||||
// name: 'mygroup',
|
||||
// consumers: 2,
|
||||
// pending: 2,
|
||||
// lastDeliveredId: '1588152489012-0'
|
||||
// }, {
|
||||
// name: 'some-other-group',
|
||||
// consumers: 1,
|
||||
// pending: 0,
|
||||
// lastDeliveredId: '1588152498034-0'
|
||||
// }]
|
||||
// );
|
||||
// });
|
||||
testUtils.testAll('xInfoGroups', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xInfoGroups('key')
|
||||
]);
|
||||
|
||||
// testUtils.testWithClient('client.xInfoGroups', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
|
||||
// assert.deepEqual(
|
||||
// await client.xInfoGroups('key'),
|
||||
// [{
|
||||
// name: 'group',
|
||||
// consumers: 0,
|
||||
// pending: 0,
|
||||
// lastDeliveredId: '0-0'
|
||||
// }]
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
assert.deepEqual(
|
||||
reply,
|
||||
[{
|
||||
name: 'group',
|
||||
consumers: 0,
|
||||
pending: 0,
|
||||
'last-delivered-id': '0-0',
|
||||
'entries-read': null,
|
||||
lag: 0
|
||||
}]
|
||||
);
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,25 +1,33 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { RedisArgument, ArrayReply, TuplesToMapReply, BlobStringReply, NumberReply, Resp2Reply, Command, NullReply } from '../RESP/types';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 2;
|
||||
export type XInfoGroupsReply = ArrayReply<TuplesToMapReply<[
|
||||
[BlobStringReply<'name'>, BlobStringReply],
|
||||
[BlobStringReply<'consumers'>, NumberReply],
|
||||
[BlobStringReply<'pending'>, NumberReply],
|
||||
[BlobStringReply<'last-delivered-id'>, NumberReply],
|
||||
/** added in 7.0 */
|
||||
[BlobStringReply<'entries-read'>, NumberReply | NullReply],
|
||||
/** added in 7.0 */
|
||||
[BlobStringReply<'lag'>, NumberReply],
|
||||
]>>;
|
||||
|
||||
// export const IS_READ_ONLY = true;
|
||||
|
||||
// export function transformArguments(key: RedisCommandArgument): RedisCommandArguments {
|
||||
// return ['XINFO', 'GROUPS', key];
|
||||
// }
|
||||
|
||||
// type XInfoGroupsReply = Array<{
|
||||
// name: RedisCommandArgument;
|
||||
// consumers: number;
|
||||
// pending: number;
|
||||
// lastDeliveredId: RedisCommandArgument;
|
||||
// }>;
|
||||
|
||||
// export function transformReply(rawReply: Array<any>): XInfoGroupsReply {
|
||||
// return rawReply.map(group => ({
|
||||
// name: group[1],
|
||||
// consumers: group[3],
|
||||
// pending: group[5],
|
||||
// lastDeliveredId: group[7]
|
||||
// }));
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(key: RedisArgument) {
|
||||
return ['XINFO', 'GROUPS', key];
|
||||
},
|
||||
transformReply: {
|
||||
2: (reply: Resp2Reply<XInfoGroupsReply>) => {
|
||||
return reply.map(group => ({
|
||||
name: group[1],
|
||||
consumers: group[3],
|
||||
pending: group[5],
|
||||
'last-delivered-id': group[7],
|
||||
'entries-read': group[9],
|
||||
lag: group[11]
|
||||
}));
|
||||
},
|
||||
3: undefined as unknown as () => XInfoGroupsReply
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,72 +1,34 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments, transformReply } from './XINFO_STREAM';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XINFO_STREAM from './XINFO_STREAM';
|
||||
|
||||
// describe('XINFO STREAM', () => {
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key'),
|
||||
// ['XINFO', 'STREAM', 'key']
|
||||
// );
|
||||
// });
|
||||
describe('XINFO STREAM', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XINFO_STREAM.transformArguments('key'),
|
||||
['XINFO', 'STREAM', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
// it('transformReply', () => {
|
||||
// assert.deepEqual(
|
||||
// transformReply([
|
||||
// 'length', 2,
|
||||
// 'radix-tree-keys', 1,
|
||||
// 'radix-tree-nodes', 2,
|
||||
// 'last-generated-id', '1538385846314-0',
|
||||
// 'groups', 2,
|
||||
// 'first-entry', ['1538385820729-0', ['foo', 'bar']],
|
||||
// 'last-entry', ['1538385846314-0', ['field', 'value']]
|
||||
// ]),
|
||||
// {
|
||||
// length: 2,
|
||||
// radixTreeKeys: 1,
|
||||
// radixTreeNodes: 2,
|
||||
// groups: 2,
|
||||
// lastGeneratedId: '1538385846314-0',
|
||||
// firstEntry: {
|
||||
// id: '1538385820729-0',
|
||||
// message: Object.create(null, {
|
||||
// foo: {
|
||||
// value: 'bar',
|
||||
// configurable: true,
|
||||
// enumerable: true
|
||||
// }
|
||||
// })
|
||||
// },
|
||||
// lastEntry: {
|
||||
// id: '1538385846314-0',
|
||||
// message: Object.create(null, {
|
||||
// field: {
|
||||
// value: 'value',
|
||||
// configurable: true,
|
||||
// enumerable: true
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
// });
|
||||
testUtils.testAll('xInfoStream', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xInfoStream('key')
|
||||
]);
|
||||
|
||||
// testUtils.testWithClient('client.xInfoStream', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
|
||||
// assert.deepEqual(
|
||||
// await client.xInfoStream('key'),
|
||||
// {
|
||||
// length: 0,
|
||||
// radixTreeKeys: 0,
|
||||
// radixTreeNodes: 1,
|
||||
// groups: 1,
|
||||
// lastGeneratedId: '0-0',
|
||||
// firstEntry: null,
|
||||
// lastEntry: null
|
||||
// }
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
assert.deepEqual(reply, {
|
||||
length: 0,
|
||||
radixTreeKeys: 0,
|
||||
radixTreeNodes: 1,
|
||||
groups: 1,
|
||||
lastGeneratedId: '0-0',
|
||||
firstEntry: null,
|
||||
lastEntry: null
|
||||
});
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -62,3 +62,80 @@
|
||||
|
||||
// return parsedReply as XInfoStreamReply;
|
||||
// }
|
||||
|
||||
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],
|
||||
[BlobStringReply<'max-deleted-entry-id'>, BlobStringReply],
|
||||
[BlobStringReply<'entries-added'>, NumberReply],
|
||||
[BlobStringReply<'recorded-first-entry-id'>, BlobStringReply],
|
||||
[BlobStringReply<'groups'>, NumberReply],
|
||||
[BlobStringReply<'first-entry'>, ReturnType<typeof transformStreamMessageReply> | NullReply],
|
||||
[BlobStringReply<'last-entry'>, ReturnType<typeof transformStreamMessageReply> | NullReply]
|
||||
]>;
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 2,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(key: RedisArgument) {
|
||||
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])
|
||||
};
|
||||
},
|
||||
3(reply: any) { // TODO: is there a "type safe" way to do it?
|
||||
if (reply instanceof Map) {
|
||||
reply.set(
|
||||
'first-entry',
|
||||
transformEntry(reply.get('first-entry'))
|
||||
);
|
||||
reply.set(
|
||||
'last-entry',
|
||||
transformEntry(reply.get('last-entry'))
|
||||
);
|
||||
} else if (reply instanceof Array) {
|
||||
reply[17] = transformEntry(reply[17]);
|
||||
reply[19] = transformEntry(reply[19]);
|
||||
} else {
|
||||
reply['first-entry'] = transformEntry(reply['first-entry']);
|
||||
reply['last-entry'] = transformEntry(reply['last-entry']);
|
||||
}
|
||||
|
||||
return reply as XInfoStreamReply;
|
||||
}
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
||||
function transformEntry(entry: StreamMessageRawReply | NullReply) {
|
||||
return entry === null ? null : transformStreamMessageReply(entry);
|
||||
}
|
||||
|
@@ -1,62 +1,60 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XPENDING';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XPENDING from './XPENDING';
|
||||
|
||||
// describe('XPENDING', () => {
|
||||
// describe('transformArguments', () => {
|
||||
// it('transformArguments', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group'),
|
||||
// ['XPENDING', 'key', 'group']
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
describe('XPENDING', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
XPENDING.transformArguments('key', 'group'),
|
||||
['XPENDING', 'key', 'group']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// describe('client.xPending', () => {
|
||||
// testUtils.testWithClient('simple', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
describe('client.xPending', () => {
|
||||
testUtils.testWithClient('simple', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.xGroupCreate('key', 'group', '$', {
|
||||
MKSTREAM: true
|
||||
}),
|
||||
client.xPending('key', 'group')
|
||||
]);
|
||||
|
||||
// assert.deepEqual(
|
||||
// await client.xPending('key', 'group'),
|
||||
// {
|
||||
// pending: 0,
|
||||
// firstId: null,
|
||||
// lastId: null,
|
||||
// consumers: null
|
||||
// }
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
assert.deepEqual(reply, {
|
||||
pending: 0,
|
||||
firstId: null,
|
||||
lastId: null,
|
||||
consumers: null
|
||||
});
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
// testUtils.testWithClient('with consumers', async client => {
|
||||
// const [,, id] = 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',
|
||||
// id: '>'
|
||||
// })
|
||||
// ]);
|
||||
testUtils.testWithClient('with consumers', async client => {
|
||||
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',
|
||||
id: '>'
|
||||
}),
|
||||
client.xPending('key', 'group')
|
||||
]);
|
||||
|
||||
// assert.deepEqual(
|
||||
// await client.xPending('key', 'group'),
|
||||
// {
|
||||
// pending: 1,
|
||||
// firstId: id,
|
||||
// lastId: id,
|
||||
// consumers: [{
|
||||
// name: 'consumer',
|
||||
// deliveriesCounter: 1
|
||||
// }]
|
||||
// }
|
||||
// );
|
||||
// }, {
|
||||
// ...GLOBAL.SERVERS.OPEN,
|
||||
// minimumDockerVersion: [6, 2]
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
assert.deepEqual(reply, {
|
||||
pending: 1,
|
||||
firstId: id,
|
||||
lastId: id,
|
||||
consumers: [{
|
||||
name: 'consumer',
|
||||
deliveriesCounter: 1
|
||||
}]
|
||||
});
|
||||
}, {
|
||||
...GLOBAL.SERVERS.OPEN,
|
||||
minimumDockerVersion: [6, 2]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,44 +1,30 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { RedisArgument, BlobStringReply, NullReply, TuplesReply, NumberReply, Command, ArrayReply } from '../RESP/types';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 1;
|
||||
type XPendingRawReply = TuplesReply<[
|
||||
pending: NumberReply,
|
||||
firstId: BlobStringReply | NullReply,
|
||||
lastId: BlobStringReply | NullReply,
|
||||
consumers: ArrayReply<TuplesReply<[
|
||||
name: BlobStringReply,
|
||||
deliveriesCounter: BlobStringReply
|
||||
]>> | NullReply
|
||||
]>;
|
||||
|
||||
// export const IS_READ_ONLY = true;
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// group: RedisCommandArgument
|
||||
// ): RedisCommandArguments {
|
||||
// return ['XPENDING', key, group];
|
||||
// }
|
||||
|
||||
// type XPendingRawReply = [
|
||||
// pending: number,
|
||||
// firstId: RedisCommandArgument | null,
|
||||
// lastId: RedisCommandArgument | null,
|
||||
// consumers: Array<[
|
||||
// name: RedisCommandArgument,
|
||||
// deliveriesCounter: RedisCommandArgument
|
||||
// ]> | null
|
||||
// ];
|
||||
|
||||
// interface XPendingReply {
|
||||
// pending: number;
|
||||
// firstId: RedisCommandArgument | null;
|
||||
// lastId: RedisCommandArgument | null;
|
||||
// consumers: Array<{
|
||||
// name: RedisCommandArgument;
|
||||
// deliveriesCounter: number;
|
||||
// }> | null;
|
||||
// }
|
||||
|
||||
// export function transformReply(reply: XPendingRawReply): XPendingReply {
|
||||
// return {
|
||||
// pending: reply[0],
|
||||
// firstId: reply[1],
|
||||
// lastId: reply[2],
|
||||
// consumers: reply[3] === null ? null : reply[3].map(([name, deliveriesCounter]) => ({
|
||||
// name,
|
||||
// deliveriesCounter: Number(deliveriesCounter)
|
||||
// }))
|
||||
// };
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(key: RedisArgument, group: RedisArgument) {
|
||||
return ['XPENDING', key, group];
|
||||
},
|
||||
transformReply(reply: XPendingRawReply) {
|
||||
return {
|
||||
pending: reply[0],
|
||||
firstId: reply[1],
|
||||
lastId: reply[2],
|
||||
consumers: reply[3] === null ? null : reply[3].map(([name, deliveriesCounter]) => ({
|
||||
name,
|
||||
deliveriesCounter: Number(deliveriesCounter)
|
||||
}))
|
||||
}
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,53 +1,67 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XPENDING_RANGE';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XPENDING_RANGE from './XPENDING_RANGE';
|
||||
|
||||
// describe('XPENDING RANGE', () => {
|
||||
// describe('transformArguments', () => {
|
||||
// it('simple', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', '-', '+', 1),
|
||||
// ['XPENDING', 'key', 'group', '-', '+', '1']
|
||||
// );
|
||||
// });
|
||||
describe('XPENDING RANGE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
XPENDING_RANGE.transformArguments('key', 'group', '-', '+', 1),
|
||||
['XPENDING', 'key', 'group', '-', '+', '1']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with IDLE', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', '-', '+', 1, {
|
||||
// IDLE: 1,
|
||||
// }),
|
||||
// ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1']
|
||||
// );
|
||||
// });
|
||||
it('with IDLE', () => {
|
||||
assert.deepEqual(
|
||||
XPENDING_RANGE.transformArguments('key', 'group', '-', '+', 1, {
|
||||
IDLE: 1,
|
||||
}),
|
||||
['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with consumer', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', '-', '+', 1, {
|
||||
// consumer: 'consumer'
|
||||
// }),
|
||||
// ['XPENDING', 'key', 'group', '-', '+', '1', 'consumer']
|
||||
// );
|
||||
// });
|
||||
it('with consumer', () => {
|
||||
assert.deepEqual(
|
||||
XPENDING_RANGE.transformArguments('key', 'group', '-', '+', 1, {
|
||||
consumer: 'consumer'
|
||||
}),
|
||||
['XPENDING', 'key', 'group', '-', '+', '1', 'consumer']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with IDLE, consumer', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', 'group', '-', '+', 1, {
|
||||
// IDLE: 1,
|
||||
// consumer: 'consumer'
|
||||
// }),
|
||||
// ['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1', 'consumer']
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
it('with IDLE, consumer', () => {
|
||||
assert.deepEqual(
|
||||
XPENDING_RANGE.transformArguments('key', 'group', '-', '+', 1, {
|
||||
IDLE: 1,
|
||||
consumer: 'consumer'
|
||||
}),
|
||||
['XPENDING', 'key', 'group', 'IDLE', '1', '-', '+', '1', 'consumer']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xPendingRange', async client => {
|
||||
// await client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// });
|
||||
testUtils.testAll('xPendingRange', async client => {
|
||||
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',
|
||||
id: '>'
|
||||
}),
|
||||
client.xPendingRange('key', 'group', '-', '+', 1)
|
||||
]);
|
||||
|
||||
// assert.deepEqual(
|
||||
// await client.xPendingRange('key', 'group', '-', '+', 1),
|
||||
// []
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
assert.ok(Array.isArray(reply));
|
||||
assert.equal(reply.length, 1);
|
||||
assert.equal(reply[0].id, id);
|
||||
assert.equal(reply[0].consumer, 'consumer');
|
||||
assert.equal(typeof reply[0].millisecondsSinceLastDelivery, 'number');
|
||||
assert.equal(reply[0].deliveriesCounter, '1');
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -32,19 +32,7 @@
|
||||
// return args;
|
||||
// }
|
||||
|
||||
// type XPendingRangeRawReply = Array<[
|
||||
// id: RedisCommandArgument,
|
||||
// consumer: RedisCommandArgument,
|
||||
// millisecondsSinceLastDelivery: number,
|
||||
// deliveriesCounter: number
|
||||
// ]>;
|
||||
|
||||
// type XPendingRangeReply = Array<{
|
||||
// id: RedisCommandArgument;
|
||||
// owner: RedisCommandArgument;
|
||||
// millisecondsSinceLastDelivery: number;
|
||||
// deliveriesCounter: number;
|
||||
// }>;
|
||||
|
||||
// export function transformReply(reply: XPendingRangeRawReply): XPendingRangeReply {
|
||||
// return reply.map(([id, owner, millisecondsSinceLastDelivery, deliveriesCounter]) => ({
|
||||
@@ -54,3 +42,56 @@
|
||||
// deliveriesCounter
|
||||
// }));
|
||||
// }
|
||||
|
||||
import { RedisArgument, ArrayReply, TuplesReply, BlobStringReply, NumberReply, Command } from '../RESP/types';
|
||||
|
||||
export interface XPendingRangeOptions {
|
||||
IDLE?: number;
|
||||
consumer?: RedisArgument;
|
||||
}
|
||||
|
||||
type XPendingRangeRawReply = ArrayReply<TuplesReply<[
|
||||
id: BlobStringReply,
|
||||
consumer: BlobStringReply,
|
||||
millisecondsSinceLastDelivery: NumberReply,
|
||||
deliveriesCounter: NumberReply
|
||||
]>>;
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(
|
||||
key: RedisArgument,
|
||||
group: RedisArgument,
|
||||
start: RedisArgument,
|
||||
end: RedisArgument,
|
||||
count: number,
|
||||
options?: XPendingRangeOptions
|
||||
) {
|
||||
const args = ['XPENDING', key, group];
|
||||
|
||||
if (options?.IDLE !== undefined) {
|
||||
args.push('IDLE', options.IDLE.toString());
|
||||
}
|
||||
|
||||
args.push(
|
||||
start,
|
||||
end,
|
||||
count.toString()
|
||||
);
|
||||
|
||||
if (options?.consumer) {
|
||||
args.push(options.consumer);
|
||||
}
|
||||
|
||||
return args;
|
||||
},
|
||||
transformReply(reply: XPendingRangeRawReply) {
|
||||
return reply.map(pending => ({
|
||||
id: pending[0],
|
||||
consumer: pending[1],
|
||||
millisecondsSinceLastDelivery: pending[2],
|
||||
deliveriesCounter: pending[3]
|
||||
}));
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,30 +1,39 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XRANGE';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XRANGE from './XRANGE';
|
||||
|
||||
// describe('XRANGE', () => {
|
||||
// describe('transformArguments', () => {
|
||||
// it('simple', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', '-', '+'),
|
||||
// ['XRANGE', 'key', '-', '+']
|
||||
// );
|
||||
// });
|
||||
describe('XRANGE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
XRANGE.transformArguments('key', '-', '+'),
|
||||
['XRANGE', 'key', '-', '+']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with COUNT', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', '-', '+', {
|
||||
// COUNT: 1
|
||||
// }),
|
||||
// ['XRANGE', 'key', '-', '+', 'COUNT', '1']
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
it('with COUNT', () => {
|
||||
assert.deepEqual(
|
||||
XRANGE.transformArguments('key', '-', '+', {
|
||||
COUNT: 1
|
||||
}),
|
||||
['XRANGE', 'key', '-', '+', 'COUNT', '1']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xRange', async client => {
|
||||
// assert.deepEqual(
|
||||
// await client.xRange('key', '+', '-'),
|
||||
// []
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
testUtils.testAll('xRange', async client => {
|
||||
const message = { field: 'value' },
|
||||
[id, reply] = await Promise.all([
|
||||
client.xAdd('key', '*', message),
|
||||
client.xRange('key', '-', '+')
|
||||
]);
|
||||
|
||||
assert.deepEqual(reply, [{
|
||||
id,
|
||||
message
|
||||
}]);
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,26 +1,29 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { RedisArgument, Command } from '../RESP/types';
|
||||
import { transformStreamMessagesReply } from './generic-transformers';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 1;
|
||||
export interface XRangeOptions {
|
||||
COUNT?: number;
|
||||
}
|
||||
|
||||
// export const IS_READ_ONLY = true;
|
||||
export function transformXRangeArguments(
|
||||
command: RedisArgument,
|
||||
key: RedisArgument,
|
||||
start: RedisArgument,
|
||||
end: RedisArgument,
|
||||
options?: XRangeOptions
|
||||
) {
|
||||
const args = [command, key, start, end];
|
||||
|
||||
// interface XRangeOptions {
|
||||
// COUNT?: number;
|
||||
// }
|
||||
if (options?.COUNT) {
|
||||
args.push('COUNT', options.COUNT.toString());
|
||||
}
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// start: RedisCommandArgument,
|
||||
// end: RedisCommandArgument,
|
||||
// options?: XRangeOptions
|
||||
// ): RedisCommandArguments {
|
||||
// const args = ['XRANGE', key, start, end];
|
||||
return args;
|
||||
}
|
||||
|
||||
// if (options?.COUNT) {
|
||||
// args.push('COUNT', options.COUNT.toString());
|
||||
// }
|
||||
|
||||
// return args;
|
||||
// }
|
||||
|
||||
// export { transformStreamMessagesReply as transformReply } from './generic-transformers';
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments: transformXRangeArguments.bind(undefined, 'XRANGE'),
|
||||
transformReply: transformStreamMessagesReply
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,87 +1,105 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { FIRST_KEY_INDEX, transformArguments } from './XREAD';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XREAD from './XREAD';
|
||||
|
||||
// describe('XREAD', () => {
|
||||
// describe('FIRST_KEY_INDEX', () => {
|
||||
// it('single stream', () => {
|
||||
// assert.equal(
|
||||
// FIRST_KEY_INDEX({ key: 'key', id: '' }),
|
||||
// 'key'
|
||||
// );
|
||||
// });
|
||||
describe('XREAD', () => {
|
||||
describe('FIRST_KEY_INDEX', () => {
|
||||
it('single stream', () => {
|
||||
assert.equal(
|
||||
XREAD.FIRST_KEY_INDEX({
|
||||
key: 'key',
|
||||
id: ''
|
||||
}),
|
||||
'key'
|
||||
);
|
||||
});
|
||||
|
||||
// it('multiple streams', () => {
|
||||
// assert.equal(
|
||||
// FIRST_KEY_INDEX([{ key: '1', id: '' }, { key: '2', id: '' }]),
|
||||
// '1'
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
it('multiple streams', () => {
|
||||
assert.equal(
|
||||
XREAD.FIRST_KEY_INDEX([{
|
||||
key: '1',
|
||||
id: ''
|
||||
}, {
|
||||
key: '2',
|
||||
id: ''
|
||||
}]),
|
||||
'1'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// describe('transformArguments', () => {
|
||||
// it('single stream', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments({
|
||||
describe('transformArguments', () => {
|
||||
it('single stream', () => {
|
||||
assert.deepEqual(
|
||||
XREAD.transformArguments({
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}),
|
||||
['XREAD', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
it('multiple streams', () => {
|
||||
assert.deepEqual(
|
||||
XREAD.transformArguments([{
|
||||
key: '1',
|
||||
id: '0-0'
|
||||
}, {
|
||||
key: '2',
|
||||
id: '0-0'
|
||||
}]),
|
||||
['XREAD', 'STREAMS', '1', '2', '0-0', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
it('with COUNT', () => {
|
||||
assert.deepEqual(
|
||||
XREAD.transformArguments({
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}, {
|
||||
COUNT: 1
|
||||
}),
|
||||
['XREAD', 'COUNT', '1', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
it('with BLOCK', () => {
|
||||
assert.deepEqual(
|
||||
XREAD.transformArguments({
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}, {
|
||||
BLOCK: 0
|
||||
}),
|
||||
['XREAD', 'BLOCK', '0', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
it('with COUNT, BLOCK', () => {
|
||||
assert.deepEqual(
|
||||
XREAD.transformArguments({
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}, {
|
||||
COUNT: 1,
|
||||
BLOCK: 0
|
||||
}),
|
||||
['XREAD', 'COUNT', '1', 'BLOCK', '0', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO
|
||||
// testUtils.testAll('client.xRead', async client => {
|
||||
// const message = { field: 'value' },
|
||||
// [, reply] = await Promise.all([
|
||||
// client.xAdd('key', '*', message),
|
||||
// client.xRead({
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }),
|
||||
// ['XREAD', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
|
||||
// it('multiple streams', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments([{
|
||||
// key: '1',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// key: '2',
|
||||
// id: '0'
|
||||
// }]),
|
||||
// ['XREAD', 'STREAMS', '1', '2', '0', '0']
|
||||
// );
|
||||
// });
|
||||
|
||||
// it('with COUNT', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments({
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// COUNT: 1
|
||||
// }),
|
||||
// ['XREAD', 'COUNT', '1', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
|
||||
// it('with BLOCK', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments({
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// BLOCK: 0
|
||||
// }),
|
||||
// ['XREAD', 'BLOCK', '0', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
|
||||
// it('with COUNT, BLOCK', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments({
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// COUNT: 1,
|
||||
// BLOCK: 0
|
||||
// }),
|
||||
// ['XREAD', 'COUNT', '1', 'BLOCK', '0', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
|
||||
// testUtils.testWithClient('client.xRead', async client => {
|
||||
// id: '0-0'
|
||||
// })
|
||||
// ])
|
||||
// assert.equal(
|
||||
// await client.xRead({
|
||||
// key: 'key',
|
||||
@@ -90,14 +108,4 @@
|
||||
// null
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
// testUtils.testWithCluster('cluster.xRead', async cluster => {
|
||||
// assert.equal(
|
||||
// await cluster.xRead({
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }),
|
||||
// null
|
||||
// );
|
||||
// }, GLOBAL.CLUSTERS.OPEN);
|
||||
// });
|
||||
});
|
||||
|
@@ -1,46 +1,55 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { Command, RedisArgument } from '../RESP/types';
|
||||
|
||||
// export const FIRST_KEY_INDEX = (streams: Array<XReadStream> | XReadStream): RedisCommandArgument => {
|
||||
// return Array.isArray(streams) ? streams[0].key : streams.key;
|
||||
// };
|
||||
export interface XReadStream {
|
||||
key: RedisArgument;
|
||||
id: RedisArgument;
|
||||
}
|
||||
|
||||
// export const IS_READ_ONLY = true;
|
||||
export type XReadStreams = Array<XReadStream> | XReadStream;
|
||||
|
||||
// interface XReadStream {
|
||||
// key: RedisCommandArgument;
|
||||
// id: RedisCommandArgument;
|
||||
// }
|
||||
export function pushXReadStreams(args: Array<RedisArgument>, streams: XReadStreams) {
|
||||
args.push('STREAMS');
|
||||
|
||||
// interface XReadOptions {
|
||||
// COUNT?: number;
|
||||
// BLOCK?: number;
|
||||
// }
|
||||
if (Array.isArray(streams)) {
|
||||
const keysStart = args.length,
|
||||
idsStart = keysStart + streams.length;
|
||||
for (let i = 0; i < streams.length; i++) {
|
||||
const stream = streams[i];
|
||||
args[keysStart + i] = stream.key;
|
||||
args[idsStart + i] = stream.id;
|
||||
}
|
||||
} else {
|
||||
args.push(streams.key, streams.id);
|
||||
}
|
||||
}
|
||||
|
||||
// export function transformArguments(
|
||||
// streams: Array<XReadStream> | XReadStream,
|
||||
// options?: XReadOptions
|
||||
// ): RedisCommandArguments {
|
||||
// const args: RedisCommandArguments = ['XREAD'];
|
||||
export interface XReadOptions {
|
||||
COUNT?: number;
|
||||
BLOCK?: number;
|
||||
}
|
||||
|
||||
// if (options?.COUNT) {
|
||||
// args.push('COUNT', options.COUNT.toString());
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX(streams: XReadStreams) {
|
||||
return Array.isArray(streams) ? streams[0].key : streams.key;
|
||||
},
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(streams: XReadStreams, options?: XReadOptions) {
|
||||
const args: Array<RedisArgument> = ['XREAD'];
|
||||
|
||||
// if (typeof options?.BLOCK === 'number') {
|
||||
// args.push('BLOCK', options.BLOCK.toString());
|
||||
// }
|
||||
if (options?.COUNT) {
|
||||
args.push('COUNT', options.COUNT.toString());
|
||||
}
|
||||
|
||||
// args.push('STREAMS');
|
||||
if (options?.BLOCK !== undefined) {
|
||||
args.push('BLOCK', options.BLOCK.toString());
|
||||
}
|
||||
|
||||
// const streamsArray = Array.isArray(streams) ? streams : [streams],
|
||||
// argsLength = args.length;
|
||||
// for (let i = 0; i < streamsArray.length; i++) {
|
||||
// const stream = streamsArray[i];
|
||||
// args[argsLength + i] = stream.key;
|
||||
// args[argsLength + streamsArray.length + i] = stream.id;
|
||||
// }
|
||||
|
||||
// return args;
|
||||
// }
|
||||
pushXReadStreams(args, streams);
|
||||
|
||||
return args;
|
||||
},
|
||||
// export { transformStreamsMessagesReply as transformReply } from './generic-transformers';
|
||||
// TODO
|
||||
transformReply: undefined as unknown as () => unknown
|
||||
} as const satisfies Command;
|
||||
|
||||
|
@@ -1,101 +1,100 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { FIRST_KEY_INDEX, transformArguments } from './XREADGROUP';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XREADGROUP from './XREADGROUP';
|
||||
|
||||
// describe('XREADGROUP', () => {
|
||||
// describe('FIRST_KEY_INDEX', () => {
|
||||
// it('single stream', () => {
|
||||
// assert.equal(
|
||||
// FIRST_KEY_INDEX('', '', { key: 'key', id: '' }),
|
||||
// 'key'
|
||||
// );
|
||||
// });
|
||||
describe('XREADGROUP', () => {
|
||||
describe('FIRST_KEY_INDEX', () => {
|
||||
it('single stream', () => {
|
||||
assert.equal(
|
||||
XREADGROUP.FIRST_KEY_INDEX('', '', { key: 'key', id: '' }),
|
||||
'key'
|
||||
);
|
||||
});
|
||||
|
||||
// it('multiple streams', () => {
|
||||
// assert.equal(
|
||||
// FIRST_KEY_INDEX('', '', [{ key: '1', id: '' }, { key: '2', id: '' }]),
|
||||
// '1'
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
it('multiple streams', () => {
|
||||
assert.equal(
|
||||
XREADGROUP.FIRST_KEY_INDEX('', '', [{ key: '1', id: '' }, { key: '2', id: '' }]),
|
||||
'1'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// describe('transformArguments', () => {
|
||||
// it('single stream', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('group', 'consumer', {
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }),
|
||||
// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
describe('transformArguments', () => {
|
||||
it('single stream', () => {
|
||||
assert.deepEqual(
|
||||
XREADGROUP.transformArguments('group', 'consumer', {
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}),
|
||||
['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
// it('multiple streams', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('group', 'consumer', [{
|
||||
// key: '1',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// key: '2',
|
||||
// id: '0'
|
||||
// }]),
|
||||
// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', '1', '2', '0', '0']
|
||||
// );
|
||||
// });
|
||||
it('multiple streams', () => {
|
||||
assert.deepEqual(
|
||||
XREADGROUP.transformArguments('group', 'consumer', [{
|
||||
key: '1',
|
||||
id: '0-0'
|
||||
}, {
|
||||
key: '2',
|
||||
id: '0-0'
|
||||
}]),
|
||||
['XREADGROUP', 'GROUP', 'group', 'consumer', 'STREAMS', '1', '2', '0-0', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with COUNT', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('group', 'consumer', {
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// COUNT: 1
|
||||
// }),
|
||||
// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
it('with COUNT', () => {
|
||||
assert.deepEqual(
|
||||
XREADGROUP.transformArguments('group', 'consumer', {
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}, {
|
||||
COUNT: 1
|
||||
}),
|
||||
['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with BLOCK', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('group', 'consumer', {
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// BLOCK: 0
|
||||
// }),
|
||||
// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'BLOCK', '0', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
it('with BLOCK', () => {
|
||||
assert.deepEqual(
|
||||
XREADGROUP.transformArguments('group', 'consumer', {
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}, {
|
||||
BLOCK: 0
|
||||
}),
|
||||
['XREADGROUP', 'GROUP', 'group', 'consumer', 'BLOCK', '0', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with NOACK', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('group', 'consumer', {
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// NOACK: true
|
||||
// }),
|
||||
// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'NOACK', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
it('with NOACK', () => {
|
||||
assert.deepEqual(
|
||||
XREADGROUP.transformArguments('group', 'consumer', {
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}, {
|
||||
NOACK: true
|
||||
}),
|
||||
['XREADGROUP', 'GROUP', 'group', 'consumer', 'NOACK', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with COUNT, BLOCK, NOACK', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('group', 'consumer', {
|
||||
// key: 'key',
|
||||
// id: '0'
|
||||
// }, {
|
||||
// COUNT: 1,
|
||||
// BLOCK: 0,
|
||||
// NOACK: true
|
||||
// }),
|
||||
// ['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'BLOCK', '0', 'NOACK', 'STREAMS', 'key', '0']
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
it('with COUNT, BLOCK, NOACK', () => {
|
||||
assert.deepEqual(
|
||||
XREADGROUP.transformArguments('group', 'consumer', {
|
||||
key: 'key',
|
||||
id: '0-0'
|
||||
}, {
|
||||
COUNT: 1,
|
||||
BLOCK: 0,
|
||||
NOACK: true
|
||||
}),
|
||||
['XREADGROUP', 'GROUP', 'group', 'consumer', 'COUNT', '1', 'BLOCK', '0', 'NOACK', 'STREAMS', 'key', '0-0']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// describe('client.xReadGroup', () => {
|
||||
// testUtils.testWithClient('null', async client => {
|
||||
// testUtils.testAll('xReadGroup - null', async client => {
|
||||
// const [, readGroupReply] = await Promise.all([
|
||||
// client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
@@ -109,7 +108,7 @@
|
||||
// assert.equal(readGroupReply, null);
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
|
||||
// testUtils.testWithClient('with a message', async client => {
|
||||
// testUtils.testAll('xReadGroup - with a message', async client => {
|
||||
// const [, id, readGroupReply] = await Promise.all([
|
||||
// client.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
@@ -135,19 +134,4 @@
|
||||
// }]
|
||||
// }]);
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
|
||||
// testUtils.testWithCluster('cluster.xReadGroup', async cluster => {
|
||||
// const [, readGroupReply] = await Promise.all([
|
||||
// cluster.xGroupCreate('key', 'group', '$', {
|
||||
// MKSTREAM: true
|
||||
// }),
|
||||
// cluster.xReadGroup('group', 'consumer', {
|
||||
// key: 'key',
|
||||
// id: '>'
|
||||
// })
|
||||
// ]);
|
||||
|
||||
// assert.equal(readGroupReply, null);
|
||||
// }, GLOBAL.CLUSTERS.OPEN);
|
||||
// });
|
||||
});
|
||||
|
@@ -1,57 +1,46 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { Command, RedisArgument } from '../RESP/types';
|
||||
import XREAD, { XReadStreams, pushXReadStreams } from './XREAD';
|
||||
|
||||
// export interface XReadGroupStream {
|
||||
// key: RedisCommandArgument;
|
||||
// id: RedisCommandArgument;
|
||||
// }
|
||||
export interface XReadGroupOptions {
|
||||
COUNT?: number;
|
||||
BLOCK?: number;
|
||||
NOACK?: boolean;
|
||||
}
|
||||
|
||||
// export interface XReadGroupOptions {
|
||||
// COUNT?: number;
|
||||
// BLOCK?: number;
|
||||
// NOACK?: true;
|
||||
// }
|
||||
export default {
|
||||
FIRST_KEY_INDEX(
|
||||
_group: RedisArgument,
|
||||
_consumer: RedisArgument,
|
||||
streams: XReadStreams
|
||||
) {
|
||||
return XREAD.FIRST_KEY_INDEX(streams);
|
||||
},
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(
|
||||
group: RedisArgument,
|
||||
consumer: RedisArgument,
|
||||
streams: XReadStreams,
|
||||
options?: XReadGroupOptions
|
||||
) {
|
||||
const args = ['XREADGROUP', group, consumer];
|
||||
|
||||
// export const FIRST_KEY_INDEX = (
|
||||
// _group: RedisCommandArgument,
|
||||
// _consumer: RedisCommandArgument,
|
||||
// streams: Array<XReadGroupStream> | XReadGroupStream
|
||||
// ): RedisCommandArgument => {
|
||||
// return Array.isArray(streams) ? streams[0].key : streams.key;
|
||||
// };
|
||||
if (options?.COUNT !== undefined) {
|
||||
args.push('COUNT', options.COUNT.toString());
|
||||
}
|
||||
|
||||
// export const IS_READ_ONLY = true;
|
||||
if (options?.BLOCK !== undefined) {
|
||||
args.push('BLOCK', options.BLOCK.toString());
|
||||
}
|
||||
|
||||
// export function transformArguments(
|
||||
// group: RedisCommandArgument,
|
||||
// consumer: RedisCommandArgument,
|
||||
// streams: Array<XReadGroupStream> | XReadGroupStream,
|
||||
// options?: XReadGroupOptions
|
||||
// ): RedisCommandArguments {
|
||||
// const args = ['XREADGROUP', 'GROUP', group, consumer];
|
||||
if (options?.NOACK) {
|
||||
args.push('NOACK');
|
||||
}
|
||||
|
||||
// if (options?.COUNT) {
|
||||
// args.push('COUNT', options.COUNT.toString());
|
||||
// }
|
||||
|
||||
// if (typeof options?.BLOCK === 'number') {
|
||||
// args.push('BLOCK', options.BLOCK.toString());
|
||||
// }
|
||||
|
||||
// if (options?.NOACK) {
|
||||
// args.push('NOACK');
|
||||
// }
|
||||
|
||||
// args.push('STREAMS');
|
||||
|
||||
// const streamsArray = Array.isArray(streams) ? streams : [streams],
|
||||
// argsLength = args.length;
|
||||
// for (let i = 0; i < streamsArray.length; i++) {
|
||||
// const stream = streamsArray[i];
|
||||
// args[argsLength + i] = stream.key;
|
||||
// args[argsLength + streamsArray.length + i] = stream.id;
|
||||
// }
|
||||
|
||||
// return args;
|
||||
// }
|
||||
pushXReadStreams(args, streams);
|
||||
|
||||
return args;
|
||||
},
|
||||
// export { transformStreamsMessagesReply as transformReply } from './generic-transformers';
|
||||
// TODO
|
||||
transformReply: undefined as unknown as () => unknown
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,30 +1,39 @@
|
||||
// import { strict as assert } from 'assert';
|
||||
// import testUtils, { GLOBAL } from '../test-utils';
|
||||
// import { transformArguments } from './XREVRANGE';
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import XREVRANGE from './XREVRANGE';
|
||||
|
||||
// describe('XREVRANGE', () => {
|
||||
// describe('transformArguments', () => {
|
||||
// it('simple', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', '-', '+'),
|
||||
// ['XREVRANGE', 'key', '-', '+']
|
||||
// );
|
||||
// });
|
||||
describe('XREVRANGE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('simple', () => {
|
||||
assert.deepEqual(
|
||||
XREVRANGE.transformArguments('key', '-', '+'),
|
||||
['XREVRANGE', 'key', '-', '+']
|
||||
);
|
||||
});
|
||||
|
||||
// it('with COUNT', () => {
|
||||
// assert.deepEqual(
|
||||
// transformArguments('key', '-', '+', {
|
||||
// COUNT: 1
|
||||
// }),
|
||||
// ['XREVRANGE', 'key', '-', '+', 'COUNT', '1']
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
it('with COUNT', () => {
|
||||
assert.deepEqual(
|
||||
XREVRANGE.transformArguments('key', '-', '+', {
|
||||
COUNT: 1
|
||||
}),
|
||||
['XREVRANGE', 'key', '-', '+', 'COUNT', '1']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// testUtils.testWithClient('client.xRevRange', async client => {
|
||||
// assert.deepEqual(
|
||||
// await client.xRevRange('key', '+', '-'),
|
||||
// []
|
||||
// );
|
||||
// }, GLOBAL.SERVERS.OPEN);
|
||||
// });
|
||||
testUtils.testAll('xRevRange', async client => {
|
||||
const message = { field: 'value' },
|
||||
[id, reply] = await Promise.all([
|
||||
client.xAdd('key', '*', message),
|
||||
client.xRevRange('key', '-', '+')
|
||||
]);
|
||||
|
||||
assert.deepEqual(reply, [{
|
||||
id,
|
||||
message
|
||||
}]);
|
||||
}, {
|
||||
client: GLOBAL.SERVERS.OPEN,
|
||||
cluster: GLOBAL.CLUSTERS.OPEN
|
||||
});
|
||||
});
|
||||
|
@@ -1,26 +1,13 @@
|
||||
// import { RedisCommandArgument, RedisCommandArguments } from '.';
|
||||
import { Command } from '../RESP/types';
|
||||
import XRANGE, { transformXRangeArguments } from './XRANGE';
|
||||
|
||||
// export const FIRST_KEY_INDEX = 1;
|
||||
export interface XRevRangeOptions {
|
||||
COUNT?: number;
|
||||
}
|
||||
|
||||
// export const IS_READ_ONLY = true;
|
||||
|
||||
// interface XRangeRevOptions {
|
||||
// COUNT?: number;
|
||||
// }
|
||||
|
||||
// export function transformArguments(
|
||||
// key: RedisCommandArgument,
|
||||
// start: RedisCommandArgument,
|
||||
// end: RedisCommandArgument,
|
||||
// options?: XRangeRevOptions
|
||||
// ): RedisCommandArguments {
|
||||
// const args = ['XREVRANGE', key, start, end];
|
||||
|
||||
// if (options?.COUNT) {
|
||||
// args.push('COUNT', options.COUNT.toString());
|
||||
// }
|
||||
|
||||
// return args;
|
||||
// }
|
||||
|
||||
// export { transformStreamMessagesReply as transformReply } from './generic-transformers';
|
||||
export default {
|
||||
FIRST_KEY_INDEX: XRANGE.FIRST_KEY_INDEX,
|
||||
IS_READ_ONLY: XRANGE.IS_READ_ONLY,
|
||||
transformArguments: transformXRangeArguments.bind(undefined, 'XREVRANGE'),
|
||||
transformReply: XRANGE.transformReply
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,6 +1,8 @@
|
||||
import { RedisArgument, SimpleStringReply, Command } from '../RESP/types';
|
||||
export interface XSetIdOptions {
|
||||
/** added in 7.0 */
|
||||
ENTRIESADDED?: number;
|
||||
/** added in 7.0 */
|
||||
MAXDELETEDID?: RedisArgument;
|
||||
}
|
||||
|
||||
|
@@ -2,6 +2,7 @@ import { NumberReply, Command, RedisArgument } from '../RESP/types';
|
||||
|
||||
export interface XTrimOptions {
|
||||
strategyModifier?: '=' | '~';
|
||||
/** added in 6.2 */
|
||||
LIMIT?: number;
|
||||
}
|
||||
|
||||
@@ -12,7 +13,8 @@ export default {
|
||||
key: RedisArgument,
|
||||
strategy: 'MAXLEN' | 'MINID',
|
||||
threshold: number,
|
||||
options?: XTrimOptions) {
|
||||
options?: XTrimOptions
|
||||
) {
|
||||
const args = ['XTRIM', key, strategy];
|
||||
|
||||
if (options?.strategyModifier) {
|
||||
|
@@ -58,39 +58,37 @@ export function transformTuplesReply(
|
||||
return message;
|
||||
}
|
||||
|
||||
export interface StreamMessageReply {
|
||||
id: RedisArgument;
|
||||
message: Record<string, RedisArgument>;
|
||||
}
|
||||
export type StreamMessageRawReply = TuplesReply<[
|
||||
id: BlobStringReply,
|
||||
message: ArrayReply<BlobStringReply>
|
||||
]>;
|
||||
|
||||
export type StreamMessagesReply = Array<StreamMessageReply>;
|
||||
|
||||
export function transformStreamMessagesReply(reply: Array<any>): StreamMessagesReply {
|
||||
const messages = [];
|
||||
|
||||
for (const [id, message] of reply) {
|
||||
messages.push({
|
||||
export function transformStreamMessageReply([id, message]: StreamMessageRawReply) {
|
||||
return {
|
||||
id,
|
||||
message: transformTuplesReply(message)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return messages;
|
||||
export type StreamMessagesRawReply = ArrayReply<StreamMessageRawReply>;
|
||||
|
||||
export function transformStreamMessagesReply(reply: StreamMessagesRawReply) {
|
||||
return reply.map(transformStreamMessageReply);
|
||||
}
|
||||
|
||||
export type StreamsMessagesReply = Array<{
|
||||
name: RedisArgument;
|
||||
messages: StreamMessagesReply;
|
||||
}> | null;
|
||||
// export type StreamsMessagesReply = Array<{
|
||||
// name: RedisArgument;
|
||||
// messages: StreamMessagesReply;
|
||||
// }> | null;
|
||||
|
||||
export function transformStreamsMessagesReply(reply: Array<any> | null): StreamsMessagesReply | null {
|
||||
if (reply === null) return null;
|
||||
// export function transformStreamsMessagesReply(reply: Array<any> | null): StreamsMessagesReply | null {
|
||||
// if (reply === null) return null;
|
||||
|
||||
return reply.map(([name, rawMessages]) => ({
|
||||
name,
|
||||
messages: transformStreamMessagesReply(rawMessages)
|
||||
}));
|
||||
}
|
||||
// return reply.map(([name, rawMessages]) => ({
|
||||
// name,
|
||||
// messages: transformStreamMessagesReply(rawMessages)
|
||||
// }));
|
||||
// }
|
||||
|
||||
export interface SortedSetMember {
|
||||
value: RedisArgument;
|
||||
|
@@ -253,10 +253,28 @@ import WATCH from './WATCH';
|
||||
import XACK from './XACK';
|
||||
import XADD_NOMKSTREAM from './XADD_NOMKSTREAM';
|
||||
import XADD from './XADD';
|
||||
import XAUTOCLAIM_JUSTID from './XAUTOCLAIM_JUSTID';
|
||||
import XAUTOCLAIM from './XAUTOCLAIM';
|
||||
import XCLAIM_JUSTID from './XCLAIM_JUSTID';
|
||||
import XCLAIM from './XCLAIM';
|
||||
import XDEL from './XDEL';
|
||||
import XGROUP_CREATE from './XGROUP_CREATE';
|
||||
import XGROUP_CREATECONSUMER from './XGROUP_CREATECONSUMER';
|
||||
import XGROUP_DELCONSUMER from './XGROUP_DELCONSUMER';
|
||||
import XGROUP_DESTROY from './XGROUP_DESTROY';
|
||||
import XGROUP_SETID from './XGROUP_SETID';
|
||||
import XINFO_CONSUMERS from './XINFO_CONSUMERS';
|
||||
import XINFO_GROUPS from './XINFO_GROUPS';
|
||||
import XINFO_STREAM from './XINFO_STREAM';
|
||||
import XLEN from './XLEN';
|
||||
import XPENDING_RANGE from './XPENDING_RANGE';
|
||||
import XPENDING from './XPENDING';
|
||||
import XRANGE from './XRANGE';
|
||||
import XREAD from './XREAD';
|
||||
import XREADGROUP from './XREADGROUP';
|
||||
import XREVRANGE from './XREVRANGE';
|
||||
import XSETID from './XSETID';
|
||||
import XTRIM from './XTRIM';
|
||||
import XLEN from './XLEN';
|
||||
import ZADD_INCR from './ZADD_INCR';
|
||||
import ZADD from './ZADD';
|
||||
import ZCARD from './ZCARD';
|
||||
@@ -554,10 +572,28 @@ type WATCH = typeof import('./WATCH').default;
|
||||
type XACK = typeof import('./XACK').default;
|
||||
type XADD_NOMKSTREAM = typeof import('./XADD_NOMKSTREAM').default;
|
||||
type XADD = typeof import('./XADD').default;
|
||||
type XAUTOCLAIM_JUSTID = typeof import('./XAUTOCLAIM_JUSTID').default;
|
||||
type XAUTOCLAIM = typeof import('./XAUTOCLAIM').default;
|
||||
type XCLAIM_JUSTID = typeof import('./XCLAIM_JUSTID').default;
|
||||
type XCLAIM = typeof import('./XCLAIM').default;
|
||||
type XDEL = typeof import('./XDEL').default;
|
||||
type XGROUP_CREATE = typeof import('./XGROUP_CREATE').default;
|
||||
type XGROUP_CREATECONSUMER = typeof import('./XGROUP_CREATECONSUMER').default;
|
||||
type XGROUP_DELCONSUMER = typeof import('./XGROUP_DELCONSUMER').default;
|
||||
type XGROUP_DESTROY = typeof import('./XGROUP_DESTROY').default;
|
||||
type XGROUP_SETID = typeof import('./XGROUP_SETID').default;
|
||||
type XINFO_CONSUMERS = typeof import('./XINFO_CONSUMERS').default;
|
||||
type XINFO_GROUPS = typeof import('./XINFO_GROUPS').default;
|
||||
type XINFO_STREAM = typeof import('./XINFO_STREAM').default;
|
||||
type XLEN = typeof import('./XLEN').default;
|
||||
type XPENDING_RANGE = typeof import('./XPENDING_RANGE').default;
|
||||
type XPENDING = typeof import('./XPENDING').default;
|
||||
type XRANGE = typeof import('./XRANGE').default;
|
||||
type XREAD = typeof import('./XREAD').default;
|
||||
type XREADGROUP = typeof import('./XREADGROUP').default;
|
||||
type XREVRANGE = typeof import('./XREVRANGE').default;
|
||||
type XSETID = typeof import('./XSETID').default;
|
||||
type XTRIM = typeof import('./XTRIM').default;
|
||||
type XLEN = typeof import('./XLEN').default;
|
||||
type ZADD_INCR = typeof import('./ZADD_INCR').default;
|
||||
type ZADD = typeof import('./ZADD').default;
|
||||
type ZCARD = typeof import('./ZCARD').default;
|
||||
@@ -1112,14 +1148,50 @@ type Commands = {
|
||||
xAddNoMkStream: XADD_NOMKSTREAM;
|
||||
XADD: XADD;
|
||||
xAdd: XADD;
|
||||
XAUTOCLAIM_JUSTID: XAUTOCLAIM_JUSTID;
|
||||
xAutoClaimJustId: XAUTOCLAIM_JUSTID;
|
||||
XAUTOCLAIM: XAUTOCLAIM;
|
||||
xAutoClaim: XAUTOCLAIM;
|
||||
XCLAIM_JUSTID: XCLAIM_JUSTID;
|
||||
xClaimJustId: XCLAIM_JUSTID;
|
||||
XCLAIM: XCLAIM;
|
||||
xClaim: XCLAIM;
|
||||
XDEL: XDEL;
|
||||
xDel: XDEL;
|
||||
XGROUP_CREATE: XGROUP_CREATE;
|
||||
xGroupCreate: XGROUP_CREATE;
|
||||
XGROUP_CREATECONSUMER: XGROUP_CREATECONSUMER;
|
||||
xGroupCreateConsumer: XGROUP_CREATECONSUMER;
|
||||
XGROUP_DELCONSUMER: XGROUP_DELCONSUMER;
|
||||
xGroupDelConsumer: XGROUP_DELCONSUMER;
|
||||
XGROUP_DESTROY: XGROUP_DESTROY;
|
||||
xGroupDestroy: XGROUP_DESTROY;
|
||||
XGROUP_SETID: XGROUP_SETID;
|
||||
xGroupSetId: XGROUP_SETID;
|
||||
XINFO_CONSUMERS: XINFO_CONSUMERS;
|
||||
xInfoConsumers: XINFO_CONSUMERS;
|
||||
XINFO_GROUPS: XINFO_GROUPS;
|
||||
xInfoGroups: XINFO_GROUPS;
|
||||
XINFO_STREAM: XINFO_STREAM;
|
||||
xInfoStream: XINFO_STREAM;
|
||||
XLEN: XLEN;
|
||||
xLen: XLEN;
|
||||
XPENDING_RANGE: XPENDING_RANGE;
|
||||
xPendingRange: XPENDING_RANGE;
|
||||
XPENDING: XPENDING;
|
||||
xPending: XPENDING;
|
||||
XRANGE: XRANGE;
|
||||
xRange: XRANGE;
|
||||
XREAD: XREAD;
|
||||
xRead: XREAD;
|
||||
XREADGROUP: XREADGROUP;
|
||||
xReadGroup: XREADGROUP;
|
||||
XREVRANGE: XREVRANGE;
|
||||
xRevRange: XREVRANGE;
|
||||
XSETID: XSETID;
|
||||
xSetId: XSETID;
|
||||
XTRIM: XTRIM;
|
||||
xTrim: XTRIM;
|
||||
XLEN: XLEN;
|
||||
xLen: XLEN;
|
||||
ZADD_INCR: ZADD_INCR;
|
||||
zAddIncr: ZADD_INCR;
|
||||
ZADD: ZADD;
|
||||
@@ -1715,14 +1787,50 @@ export default {
|
||||
xAddNoMkStream: XADD_NOMKSTREAM,
|
||||
XADD,
|
||||
xAdd: XADD,
|
||||
XAUTOCLAIM_JUSTID,
|
||||
xAutoClaimJustId: XAUTOCLAIM_JUSTID,
|
||||
XAUTOCLAIM,
|
||||
xAutoClaim: XAUTOCLAIM,
|
||||
XCLAIM_JUSTID,
|
||||
xClaimJustId: XCLAIM_JUSTID,
|
||||
XCLAIM,
|
||||
xClaim: XCLAIM,
|
||||
XDEL,
|
||||
xDel: XDEL,
|
||||
XGROUP_CREATE,
|
||||
xGroupCreate: XGROUP_CREATE,
|
||||
XGROUP_CREATECONSUMER,
|
||||
xGroupCreateConsumer: XGROUP_CREATECONSUMER,
|
||||
XGROUP_DELCONSUMER,
|
||||
xGroupDelConsumer: XGROUP_DELCONSUMER,
|
||||
XGROUP_DESTROY,
|
||||
xGroupDestroy: XGROUP_DESTROY,
|
||||
XGROUP_SETID,
|
||||
xGroupSetId: XGROUP_SETID,
|
||||
XINFO_CONSUMERS,
|
||||
xInfoConsumers: XINFO_CONSUMERS,
|
||||
XINFO_GROUPS,
|
||||
xInfoGroups: XINFO_GROUPS,
|
||||
XINFO_STREAM,
|
||||
xInfoStream: XINFO_STREAM,
|
||||
XLEN,
|
||||
xLen: XLEN,
|
||||
XPENDING_RANGE,
|
||||
xPendingRange: XPENDING_RANGE,
|
||||
XPENDING,
|
||||
xPending: XPENDING,
|
||||
XRANGE,
|
||||
xRange: XRANGE,
|
||||
XREAD,
|
||||
xRead: XREAD,
|
||||
XREADGROUP,
|
||||
xReadGroup: XREADGROUP,
|
||||
XREVRANGE,
|
||||
xRevRange: XREVRANGE,
|
||||
XSETID,
|
||||
xSetId: XSETID,
|
||||
XTRIM,
|
||||
xTrim: XTRIM,
|
||||
XLEN,
|
||||
xLen: XLEN,
|
||||
ZADD_INCR,
|
||||
zAddIncr: ZADD_INCR,
|
||||
ZADD,
|
||||
|
200
test/package-lock.json
generated
200
test/package-lock.json
generated
@@ -9,69 +9,19 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@redis/client": "^1.5.7",
|
||||
"ioredis": "^5.3.2",
|
||||
"local": "file:../packages/client",
|
||||
"redis": "^4.6.6",
|
||||
"redis-om": "^0.3.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@ioredis/commands": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
|
||||
},
|
||||
"node_modules/@redis/bloom": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
|
||||
"integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
"@redis/client": "next"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/client": {
|
||||
"version": "1.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz",
|
||||
"integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==",
|
||||
"version": "2.0.0-next.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-2.0.0-next.2.tgz",
|
||||
"integrity": "sha512-+sf9n+PBHac2xXSofSX0x79cYa5H4ighu80F993q4H1T109ZthFNGBmg33DfwfPrDMKc256qTXvsb0lCqzwMmg==",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.2",
|
||||
"generic-pool": "3.9.0",
|
||||
"yallist": "4.0.0"
|
||||
"generic-pool": "3.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/graph": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz",
|
||||
"integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/json": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz",
|
||||
"integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/search": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz",
|
||||
"integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/time-series": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz",
|
||||
"integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/cluster-key-slot": {
|
||||
@@ -82,30 +32,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/generic-pool": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
|
||||
@@ -113,120 +39,6 @@
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/ioredis": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz",
|
||||
"integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==",
|
||||
"dependencies": {
|
||||
"@ioredis/commands": "^1.1.1",
|
||||
"cluster-key-slot": "^1.1.0",
|
||||
"debug": "^4.3.4",
|
||||
"denque": "^2.1.0",
|
||||
"lodash.defaults": "^4.2.0",
|
||||
"lodash.isarguments": "^3.1.0",
|
||||
"redis-errors": "^1.2.0",
|
||||
"redis-parser": "^3.0.0",
|
||||
"standard-as-callback": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ioredis"
|
||||
}
|
||||
},
|
||||
"node_modules/local": {
|
||||
"name": "@redis/client",
|
||||
"version": "2.0.0-next.1",
|
||||
"resolved": "file:../packages/client",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.2",
|
||||
"generic-pool": "3.9.0",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.defaults": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
|
||||
},
|
||||
"node_modules/lodash.isarguments": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/redis": {
|
||||
"version": "4.6.6",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-4.6.6.tgz",
|
||||
"integrity": "sha512-aLs2fuBFV/VJ28oLBqYykfnhGGkFxvx0HdCEBYdJ99FFbSEMZ7c1nVKwR6ZRv+7bb7JnC0mmCzaqu8frgOYhpA==",
|
||||
"dependencies": {
|
||||
"@redis/bloom": "1.2.0",
|
||||
"@redis/client": "1.5.7",
|
||||
"@redis/graph": "1.1.0",
|
||||
"@redis/json": "1.0.4",
|
||||
"@redis/search": "1.1.2",
|
||||
"@redis/time-series": "1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-errors": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-om": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/redis-om/-/redis-om-0.3.6.tgz",
|
||||
"integrity": "sha512-WRmrAm1n1EQIQbEwbfqpceuxHgr7LKOZ471c/KGxyOTVFFm53E0S7vFSZA7a1Jnga7aHTOYqLhhMWE0lKKdsNw==",
|
||||
"dependencies": {
|
||||
"redis": "^4.0.4",
|
||||
"ulid": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-parser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
|
||||
"dependencies": {
|
||||
"redis-errors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/standard-as-callback": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
||||
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
|
||||
},
|
||||
"node_modules/ulid": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz",
|
||||
"integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==",
|
||||
"bin": {
|
||||
"ulid": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,10 +10,6 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@redis/client": "^1.5.7",
|
||||
"ioredis": "^5.3.2",
|
||||
"local": "file:../packages/client",
|
||||
"redis": "^4.6.6",
|
||||
"redis-om": "^0.3.6"
|
||||
"@redis/client": "next"
|
||||
}
|
||||
}
|
||||
|
33
test/test.js
33
test/test.js
@@ -1,26 +1,21 @@
|
||||
import { createClient } from '@redis/client';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
import { RESP_TYPES, createClient } from '@redis/client';
|
||||
|
||||
const client = createClient();
|
||||
const client = createClient({
|
||||
RESP: 3,
|
||||
commandOptions: {
|
||||
typeMapping: {
|
||||
[RESP_TYPES.MAP]: Map
|
||||
}
|
||||
}
|
||||
});
|
||||
client.on('error', err => console.error(err));
|
||||
|
||||
await client.connect();
|
||||
|
||||
await client.set('key', 'a'.repeat(1_000));
|
||||
|
||||
throw 'a';
|
||||
|
||||
while (true) {
|
||||
const promises = [];
|
||||
for (let i = 0; i < 20_000; i++) {
|
||||
promises.push(client.sendCommand(['HMSET', `aa${i.toString()}`, 'txt1', Math.random().toString()]));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
console.log(
|
||||
await client.dbSize(),
|
||||
(await client.info('MEMORY')).split('\n')[1]
|
||||
);
|
||||
await client.flushAll(),
|
||||
await client.hSet('key', 'field', 'value'),
|
||||
await client.hGetAll('key')
|
||||
)
|
||||
|
||||
await setTimeout(1000);
|
||||
}
|
||||
client.destroy();
|
||||
|
Reference in New Issue
Block a user