From 23d44fdd51164412bb4e86960ea2042b2121484f Mon Sep 17 00:00:00 2001 From: Avital-Fine Date: Tue, 22 Mar 2022 16:08:48 +0100 Subject: [PATCH] Support new muilti pop commands --- packages/client/lib/cluster/commands.ts | 12 +++++ packages/client/lib/commands/BLMPOP.spec.ts | 37 ++++++++++++++ packages/client/lib/commands/BLMPOP.ts | 14 ++++++ packages/client/lib/commands/BZMPOP.spec.ts | 37 ++++++++++++++ packages/client/lib/commands/BZMPOP.ts | 14 ++++++ packages/client/lib/commands/LMPOP.spec.ts | 37 ++++++++++++++ packages/client/lib/commands/LMPOP.ts | 20 ++++++++ packages/client/lib/commands/ZMPOP.spec.ts | 37 ++++++++++++++ packages/client/lib/commands/ZMPOP.ts | 26 ++++++++++ .../lib/commands/generic-transformers.ts | 50 +++++++++++++++++++ 10 files changed, 284 insertions(+) create mode 100644 packages/client/lib/commands/BLMPOP.spec.ts create mode 100644 packages/client/lib/commands/BLMPOP.ts create mode 100644 packages/client/lib/commands/BZMPOP.spec.ts create mode 100644 packages/client/lib/commands/BZMPOP.ts create mode 100644 packages/client/lib/commands/LMPOP.spec.ts create mode 100644 packages/client/lib/commands/LMPOP.ts create mode 100644 packages/client/lib/commands/ZMPOP.spec.ts create mode 100644 packages/client/lib/commands/ZMPOP.ts diff --git a/packages/client/lib/cluster/commands.ts b/packages/client/lib/cluster/commands.ts index bbfe237b09..8e6f014d49 100644 --- a/packages/client/lib/cluster/commands.ts +++ b/packages/client/lib/cluster/commands.ts @@ -6,9 +6,11 @@ import * as BITFIELD from '../commands/BITFIELD'; import * as BITOP from '../commands/BITOP'; import * as BITPOS from '../commands/BITPOS'; import * as BLMOVE from '../commands/BLMOVE'; +import * as BLMPOP from '../commands/BLMPOP'; import * as BLPOP from '../commands/BLPOP'; import * as BRPOP from '../commands/BRPOP'; import * as BRPOPLPUSH from '../commands/BRPOPLPUSH'; +import * as BZMPOP from '../commands/BZMPOP'; import * as BZPOPMAX from '../commands/BZPOPMAX'; import * as BZPOPMIN from '../commands/BZPOPMIN'; import * as COPY from '../commands/COPY'; @@ -58,6 +60,7 @@ import * as LINDEX from '../commands/LINDEX'; import * as LINSERT from '../commands/LINSERT'; import * as LLEN from '../commands/LLEN'; import * as LMOVE from '../commands/LMOVE'; +import * as LMPOP from '../commands/LMPOP'; import * as LPOP_COUNT from '../commands/LPOP_COUNT'; import * as LPOP from '../commands/LPOP'; import * as LPOS_COUNT from '../commands/LPOS_COUNT'; @@ -153,6 +156,7 @@ import * as ZINTER from '../commands/ZINTER'; import * as ZINTERCARD from '../commands/ZINTERCARD'; import * as ZINTERSTORE from '../commands/ZINTERSTORE'; import * as ZLEXCOUNT from '../commands/ZLEXCOUNT'; +import * as ZMPOP from '../commands/ZMPOP'; import * as ZMSCORE from '../commands/ZMSCORE'; import * as ZPOPMAX_COUNT from '../commands/ZPOPMAX_COUNT'; import * as ZPOPMAX from '../commands/ZPOPMAX'; @@ -194,12 +198,16 @@ export default { bitPos: BITPOS, BLMOVE, blMove: BLMOVE, + BLMPOP, + blmPop: BLMPOP, BLPOP, blPop: BLPOP, BRPOP, brPop: BRPOP, BRPOPLPUSH, brPopLPush: BRPOPLPUSH, + BZMPOP, + bzmPop: BZMPOP, BZPOPMAX, bzPopMax: BZPOPMAX, BZPOPMIN, @@ -298,6 +306,8 @@ export default { lLen: LLEN, LMOVE, lMove: LMOVE, + LMPOP, + lmPop: LMPOP, LPOP_COUNT, lPopCount: LPOP_COUNT, LPOP, @@ -488,6 +498,8 @@ export default { zInterStore: ZINTERSTORE, ZLEXCOUNT, zLexCount: ZLEXCOUNT, + ZMPOP, + zmPop: ZMPOP, ZMSCORE, zmScore: ZMSCORE, ZPOPMAX_COUNT, diff --git a/packages/client/lib/commands/BLMPOP.spec.ts b/packages/client/lib/commands/BLMPOP.spec.ts new file mode 100644 index 0000000000..6a10540487 --- /dev/null +++ b/packages/client/lib/commands/BLMPOP.spec.ts @@ -0,0 +1,37 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './BLMPOP'; + +describe.only('BLMPOP', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments(0, 'key', { + SIDE: 'LEFT' + }), + ['BLMPOP', '0', '1', 'key', 'LEFT'] + ); + }); + + it('with score and count', () => { + assert.deepEqual( + transformArguments(0, 'key', { + SIDE: 'LEFT', + COUNT: 2 + }), + ['BLMPOP', '0', '1', 'key', 'LEFT', 'COUNT', '2'] + ); + }); + }); + + testUtils.testWithClient('client.zmScore', async client => { + assert.deepEqual( + await client.blmPop(0, 'key', { + SIDE: 'LEFT' + }), + null + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/BLMPOP.ts b/packages/client/lib/commands/BLMPOP.ts new file mode 100644 index 0000000000..343f077b3e --- /dev/null +++ b/packages/client/lib/commands/BLMPOP.ts @@ -0,0 +1,14 @@ +import { RedisCommandArguments } from '.'; +import { transformLMPopArguments, LMPopOptions } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 3; + +export function transformArguments( + timeout: number, + keys: string | Array, + options: LMPopOptions +): RedisCommandArguments { + return transformLMPopArguments(['BLMPOP', timeout.toString()], keys, options); +} + +export { transformReply } from './LMPOP'; diff --git a/packages/client/lib/commands/BZMPOP.spec.ts b/packages/client/lib/commands/BZMPOP.spec.ts new file mode 100644 index 0000000000..1d66b2a8db --- /dev/null +++ b/packages/client/lib/commands/BZMPOP.spec.ts @@ -0,0 +1,37 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './BZMPOP'; + +describe.only('BZMPOP', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments(0, 'key', { + SCORE: 'MIN' + }), + ['BZMPOP', '0', '1', 'key', 'MIN'] + ); + }); + + it('with score and count', () => { + assert.deepEqual( + transformArguments(0, 'key', { + SCORE: 'MIN', + COUNT: 2 + }), + ['BZMPOP', '0', '1', 'key', 'MIN', 'COUNT', '2'] + ); + }); + }); + + testUtils.testWithClient('client.zmScore', async client => { + assert.deepEqual( + await client.bzmPop(0, 'key', { + SCORE: 'MAX' + }), + null + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/BZMPOP.ts b/packages/client/lib/commands/BZMPOP.ts new file mode 100644 index 0000000000..25336b8ae5 --- /dev/null +++ b/packages/client/lib/commands/BZMPOP.ts @@ -0,0 +1,14 @@ +import { RedisCommandArguments } from '.'; +import { transformZMPopArguments, ZMPopOptions } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 3; + +export function transformArguments( + timeout: number, + keys: string | Array, + options: ZMPopOptions +): RedisCommandArguments { + return transformZMPopArguments(['BZMPOP', timeout.toString()], keys, options); +} + +export { transformReply } from './ZMPOP'; diff --git a/packages/client/lib/commands/LMPOP.spec.ts b/packages/client/lib/commands/LMPOP.spec.ts new file mode 100644 index 0000000000..c28c46a576 --- /dev/null +++ b/packages/client/lib/commands/LMPOP.spec.ts @@ -0,0 +1,37 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './LMPOP'; + +describe.only('LMPOP', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('key', { + SIDE: 'LEFT' + }), + ['LMPOP', '1', 'key', 'LEFT'] + ); + }); + + it('with score and count', () => { + assert.deepEqual( + transformArguments('key', { + SIDE: 'LEFT', + COUNT: 2 + }), + ['LMPOP', '1', 'key', 'LEFT', 'COUNT', '2'] + ); + }); + }); + + testUtils.testWithClient('client.zmScore', async client => { + assert.deepEqual( + await client.lmPop('key', { + SIDE: 'RIGHT' + }), + null + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/LMPOP.ts b/packages/client/lib/commands/LMPOP.ts new file mode 100644 index 0000000000..e9034a1dc5 --- /dev/null +++ b/packages/client/lib/commands/LMPOP.ts @@ -0,0 +1,20 @@ +import { RedisCommandArguments } from '.'; +import { transformLMPopArguments, LMPopOptions } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 2; + +export const IS_READ_ONLY = true; + +export function transformArguments( + keys: string | Array, + options: LMPopOptions +): RedisCommandArguments { + return transformLMPopArguments(['LMPOP'], keys, options); +} + +type LMPopReply = null | [ + key: string, + elements: Array +]; + +export declare function transformReply(): LMPopReply; diff --git a/packages/client/lib/commands/ZMPOP.spec.ts b/packages/client/lib/commands/ZMPOP.spec.ts new file mode 100644 index 0000000000..6752ecde2b --- /dev/null +++ b/packages/client/lib/commands/ZMPOP.spec.ts @@ -0,0 +1,37 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ZMPOP'; + +describe.only('ZMPOP', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('key', { + SCORE: 'MIN' + }), + ['ZMPOP', '1', 'key', 'MIN'] + ); + }); + + it('with score and count', () => { + assert.deepEqual( + transformArguments('key', { + SCORE: 'MIN', + COUNT: 2 + }), + ['ZMPOP', '1', 'key', 'MIN', 'COUNT', '2'] + ); + }); + }); + + testUtils.testWithClient('client.zmScore', async client => { + assert.deepEqual( + await client.zmPop('key', { + SCORE: 'MAX' + }), + null + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/ZMPOP.ts b/packages/client/lib/commands/ZMPOP.ts new file mode 100644 index 0000000000..556722fc51 --- /dev/null +++ b/packages/client/lib/commands/ZMPOP.ts @@ -0,0 +1,26 @@ +import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { transformSortedSetMemberReply, transformZMPopArguments, ZMember, ZMPopOptions } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 2; + +export const IS_READ_ONLY = true; + +export function transformArguments( + keys: string | Array, + options: ZMPopOptions +): RedisCommandArguments { + return transformZMPopArguments(['ZMPOP'], keys, options); +} + +type ZMPopRawReply = null | [string, Array<[RedisCommandArgument, RedisCommandArgument]>]; + +type ZMPopReply = null | [ + key: string, + elements: Array +]; + +export function transformReply(reply: ZMPopRawReply): ZMPopReply { + if (reply == null) return null; + + return [reply[0], reply[1].map(transformSortedSetMemberReply)]; +} diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 0799476ae6..ed319f08d8 100644 --- a/packages/client/lib/commands/generic-transformers.ts +++ b/packages/client/lib/commands/generic-transformers.ts @@ -131,6 +131,13 @@ export function transformSortedSetMemberNullReply( ): ZMember | null { if (!reply.length) return null; + return transformSortedSetMemberReply(reply); +} + +export function transformSortedSetMemberReply( + reply: [RedisCommandArgument, RedisCommandArgument] +): ZMember { + return { value: reply[0], score: transformNumberInfinityReply(reply[1]) @@ -150,6 +157,49 @@ export function transformSortedSetWithScoresReply(reply: Array, + options: ZMPopOptions +): RedisCommandArguments { + pushVerdictArgument(args, keys); + + args.push(options.SCORE); + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } + + return args; +} + +export interface LMPopOptions { + SIDE: 'LEFT' | 'RIGHT'; + COUNT?: number; +} + +export function transformLMPopArguments( + args: RedisCommandArguments, + keys: string | Array, + options: LMPopOptions +): RedisCommandArguments { + pushVerdictArgument(args, keys); + + args.push(options.SIDE); + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } + + return args; +} + type GeoCountArgument = number | { value: number; ANY?: true