From b1a0b48d2cd17cfa5a5de2bcd2ed05b3f7ef159a Mon Sep 17 00:00:00 2001 From: Avital Fine <98389525+Avital-Fine@users.noreply.github.com> Date: Mon, 25 Apr 2022 14:50:43 +0300 Subject: [PATCH] Support new muilti pop commands (#2051) * Support new muilti pop commands * remove .only * clean code * fix for 4558ec6a31d2904154c896e8325f09ae33a9ea32 * fix tests Co-authored-by: leibale --- packages/client/lib/cluster/commands.ts | 12 +++++ packages/client/lib/commands/BLMOVE.ts | 6 +-- packages/client/lib/commands/BLMPOP.spec.ts | 32 +++++++++++ packages/client/lib/commands/BLMPOP.ts | 20 +++++++ packages/client/lib/commands/BLPOP.spec.ts | 2 +- packages/client/lib/commands/BZMPOP.spec.ts | 32 +++++++++++ packages/client/lib/commands/BZMPOP.ts | 20 +++++++ packages/client/lib/commands/BZPOPMAX.spec.ts | 2 +- packages/client/lib/commands/BZPOPMIN.spec.ts | 2 +- packages/client/lib/commands/LMOVE.ts | 7 ++- packages/client/lib/commands/LMPOP.spec.ts | 32 +++++++++++ packages/client/lib/commands/LMPOP.ts | 22 ++++++++ packages/client/lib/commands/ZMPOP.spec.ts | 32 +++++++++++ packages/client/lib/commands/ZMPOP.ts | 34 ++++++++++++ .../lib/commands/generic-transformers.ts | 53 +++++++++++++++++++ 15 files changed, 298 insertions(+), 10 deletions(-) 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 4a2c7e8503..91e589e127 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'; @@ -59,6 +61,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'; @@ -161,6 +164,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'; @@ -202,12 +206,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, @@ -308,6 +316,8 @@ export default { lLen: LLEN, LMOVE, lMove: LMOVE, + LMPOP, + lmPop: LMPOP, LPOP_COUNT, lPopCount: LPOP_COUNT, LPOP, @@ -512,6 +522,8 @@ export default { zInterStore: ZINTERSTORE, ZLEXCOUNT, zLexCount: ZLEXCOUNT, + ZMPOP, + zmPop: ZMPOP, ZMSCORE, zmScore: ZMSCORE, ZPOPMAX_COUNT, diff --git a/packages/client/lib/commands/BLMOVE.ts b/packages/client/lib/commands/BLMOVE.ts index 329192f634..ee808e70fc 100644 --- a/packages/client/lib/commands/BLMOVE.ts +++ b/packages/client/lib/commands/BLMOVE.ts @@ -1,13 +1,13 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; -import { LMoveSide } from './LMOVE'; +import { ListSide } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; export function transformArguments( source: RedisCommandArgument, destination: RedisCommandArgument, - sourceDirection: LMoveSide, - destinationDirection: LMoveSide, + sourceDirection: ListSide, + destinationDirection: ListSide, timeout: number ): RedisCommandArguments { return [ diff --git a/packages/client/lib/commands/BLMPOP.spec.ts b/packages/client/lib/commands/BLMPOP.spec.ts new file mode 100644 index 0000000000..9a4a6c96a2 --- /dev/null +++ b/packages/client/lib/commands/BLMPOP.spec.ts @@ -0,0 +1,32 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './BLMPOP'; + +describe('BLMPOP', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments(0, 'key', 'LEFT'), + ['BLMPOP', '0', '1', 'key', 'LEFT'] + ); + }); + + it('with COUNT', () => { + assert.deepEqual( + transformArguments(0, 'key', 'LEFT', { + COUNT: 2 + }), + ['BLMPOP', '0', '1', 'key', 'LEFT', 'COUNT', '2'] + ); + }); + }); + + testUtils.testWithClient('client.blmPop', async client => { + assert.deepEqual( + await client.blmPop(1, 'key', 'RIGHT'), + 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..11bfad8b99 --- /dev/null +++ b/packages/client/lib/commands/BLMPOP.ts @@ -0,0 +1,20 @@ +import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { transformLMPopArguments, LMPopOptions, ListSide } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 3; + +export function transformArguments( + timeout: number, + keys: RedisCommandArgument | Array, + side: ListSide, + options?: LMPopOptions +): RedisCommandArguments { + return transformLMPopArguments( + ['BLMPOP', timeout.toString()], + keys, + side, + options + ); +} + +export { transformReply } from './LMPOP'; diff --git a/packages/client/lib/commands/BLPOP.spec.ts b/packages/client/lib/commands/BLPOP.spec.ts index 4b93c0b43b..84920c851e 100644 --- a/packages/client/lib/commands/BLPOP.spec.ts +++ b/packages/client/lib/commands/BLPOP.spec.ts @@ -65,7 +65,7 @@ describe('BLPOP', () => { 'key', 1 ), - cluster.lPush('key', 'element'), + cluster.lPush('key', 'element') ]); assert.deepEqual( diff --git a/packages/client/lib/commands/BZMPOP.spec.ts b/packages/client/lib/commands/BZMPOP.spec.ts new file mode 100644 index 0000000000..b35d971f0a --- /dev/null +++ b/packages/client/lib/commands/BZMPOP.spec.ts @@ -0,0 +1,32 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './BZMPOP'; + +describe('BZMPOP', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments(0, 'key', 'MIN'), + ['BZMPOP', '0', '1', 'key', 'MIN'] + ); + }); + + it('with COUNT', () => { + assert.deepEqual( + transformArguments(0, 'key', 'MIN', { + COUNT: 2 + }), + ['BZMPOP', '0', '1', 'key', 'MIN', 'COUNT', '2'] + ); + }); + }); + + testUtils.testWithClient('client.bzmPop', async client => { + assert.deepEqual( + await client.bzmPop(1, 'key', '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..e4e9699cbd --- /dev/null +++ b/packages/client/lib/commands/BZMPOP.ts @@ -0,0 +1,20 @@ +import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { SortedSetSide, transformZMPopArguments, ZMPopOptions } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 3; + +export function transformArguments( + timeout: number, + keys: RedisCommandArgument | Array, + side: SortedSetSide, + options?: ZMPopOptions +): RedisCommandArguments { + return transformZMPopArguments( + ['BZMPOP', timeout.toString()], + keys, + side, + options + ); +} + +export { transformReply } from './ZMPOP'; diff --git a/packages/client/lib/commands/BZPOPMAX.spec.ts b/packages/client/lib/commands/BZPOPMAX.spec.ts index e1c3747846..d5c1743712 100644 --- a/packages/client/lib/commands/BZPOPMAX.spec.ts +++ b/packages/client/lib/commands/BZPOPMAX.spec.ts @@ -45,7 +45,7 @@ describe('BZPOPMAX', () => { client.bzPopMax( commandOptions({ isolated: true }), 'key', - 0 + 1 ), client.zAdd('key', [{ value: '1', diff --git a/packages/client/lib/commands/BZPOPMIN.spec.ts b/packages/client/lib/commands/BZPOPMIN.spec.ts index 4cd1ec1b22..0573a4ac89 100644 --- a/packages/client/lib/commands/BZPOPMIN.spec.ts +++ b/packages/client/lib/commands/BZPOPMIN.spec.ts @@ -45,7 +45,7 @@ describe('BZPOPMIN', () => { client.bzPopMin( commandOptions({ isolated: true }), 'key', - 0 + 1 ), client.zAdd('key', [{ value: '1', diff --git a/packages/client/lib/commands/LMOVE.ts b/packages/client/lib/commands/LMOVE.ts index 7332d1a007..849c6385f5 100644 --- a/packages/client/lib/commands/LMOVE.ts +++ b/packages/client/lib/commands/LMOVE.ts @@ -1,14 +1,13 @@ import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { ListSide } from './generic-transformers'; export const FIRST_KEY_INDEX = 1; -export type LMoveSide = 'LEFT' | 'RIGHT'; - export function transformArguments( source: RedisCommandArgument, destination: RedisCommandArgument, - sourceSide: LMoveSide, - destinationSide: LMoveSide + sourceSide: ListSide, + destinationSide: ListSide ): RedisCommandArguments { return [ 'LMOVE', diff --git a/packages/client/lib/commands/LMPOP.spec.ts b/packages/client/lib/commands/LMPOP.spec.ts new file mode 100644 index 0000000000..a3c36f9021 --- /dev/null +++ b/packages/client/lib/commands/LMPOP.spec.ts @@ -0,0 +1,32 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './LMPOP'; + +describe('LMPOP', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('key', 'LEFT'), + ['LMPOP', '1', 'key', 'LEFT'] + ); + }); + + it('with COUNT', () => { + assert.deepEqual( + transformArguments('key', 'LEFT', { + COUNT: 2 + }), + ['LMPOP', '1', 'key', 'LEFT', 'COUNT', '2'] + ); + }); + }); + + testUtils.testWithClient('client.lmPop', async client => { + assert.deepEqual( + await client.lmPop('key', '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..29d868b982 --- /dev/null +++ b/packages/client/lib/commands/LMPOP.ts @@ -0,0 +1,22 @@ +import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { transformLMPopArguments, LMPopOptions, ListSide } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 2; + +export function transformArguments( + keys: RedisCommandArgument | Array, + side: ListSide, + options?: LMPopOptions +): RedisCommandArguments { + return transformLMPopArguments( + ['LMPOP'], + keys, + side, + options + ); +} + +export declare function transformReply(): null | [ + key: string, + elements: Array +]; diff --git a/packages/client/lib/commands/ZMPOP.spec.ts b/packages/client/lib/commands/ZMPOP.spec.ts new file mode 100644 index 0000000000..84f51e67b7 --- /dev/null +++ b/packages/client/lib/commands/ZMPOP.spec.ts @@ -0,0 +1,32 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './ZMPOP'; + +describe('ZMPOP', () => { + testUtils.isVersionGreaterThanHook([7, 0]); + + describe('transformArguments', () => { + it('simple', () => { + assert.deepEqual( + transformArguments('key', 'MIN'), + ['ZMPOP', '1', 'key', 'MIN'] + ); + }); + + it('with score and count', () => { + assert.deepEqual( + transformArguments('key', 'MIN', { + COUNT: 2 + }), + ['ZMPOP', '1', 'key', 'MIN', 'COUNT', '2'] + ); + }); + }); + + testUtils.testWithClient('client.zmPop', async client => { + assert.deepEqual( + await client.zmPop('key', 'MIN'), + 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..0baa46bbf0 --- /dev/null +++ b/packages/client/lib/commands/ZMPOP.ts @@ -0,0 +1,34 @@ +import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { SortedSetSide, transformSortedSetMemberReply, transformZMPopArguments, ZMember, ZMPopOptions } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 2; + +export function transformArguments( + keys: RedisCommandArgument | Array, + side: SortedSetSide, + options?: ZMPopOptions +): RedisCommandArguments { + return transformZMPopArguments( + ['ZMPOP'], + keys, + side, + options + ); +} + +type ZMPopRawReply = null | [ + key: string, + elements: Array<[RedisCommandArgument, RedisCommandArgument]> +]; + +type ZMPopReply = null | { + key: string, + elements: Array +}; + +export function transformReply(reply: ZMPopRawReply): ZMPopReply { + return reply === null ? null : { + key: reply[0], + elements: reply[1].map(transformSortedSetMemberReply) + }; +} diff --git a/packages/client/lib/commands/generic-transformers.ts b/packages/client/lib/commands/generic-transformers.ts index 7850d22ed4..e881822fb4 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,52 @@ export function transformSortedSetWithScoresReply(reply: Array, + side: SortedSetSide, + options?: ZMPopOptions +): RedisCommandArguments { + pushVerdictArgument(args, keys); + + args.push(side); + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } + + return args; +} + +export type ListSide = 'LEFT' | 'RIGHT'; + +export interface LMPopOptions { + COUNT?: number; +} + +export function transformLMPopArguments( + args: RedisCommandArguments, + keys: RedisCommandArgument | Array, + side: ListSide, + options?: LMPopOptions +): RedisCommandArguments { + pushVerdictArgument(args, keys); + + args.push(side); + + if (options?.COUNT) { + args.push('COUNT', options.COUNT.toString()); + } + + return args; +} + type GeoCountArgument = number | { value: number; ANY?: true