1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-10 11:43:01 +03:00

fix #1636 - fix WatchError

This commit is contained in:
leibale
2021-08-24 15:43:19 -04:00
parent 99b125fd07
commit f1bf0beebf
3 changed files with 40 additions and 28 deletions

View File

@@ -2,9 +2,10 @@ import { strict as assert } from 'assert';
import { once } from 'events'; import { once } from 'events';
import { itWithClient, TEST_REDIS_SERVERS, TestRedisServers, waitTillBeenCalled, isRedisVersionGreaterThan } from './test-utils'; import { itWithClient, TEST_REDIS_SERVERS, TestRedisServers, waitTillBeenCalled, isRedisVersionGreaterThan } from './test-utils';
import RedisClient from './client'; import RedisClient from './client';
import { AbortError } from './errors'; import { AbortError, WatchError } from './errors';
import { defineScript } from './lua-script'; import { defineScript } from './lua-script';
import { spy } from 'sinon'; import { spy } from 'sinon';
import { commandOptions } from './command-options';
export const SQUARE_SCRIPT = defineScript({ export const SQUARE_SCRIPT = defineScript({
NUMBER_OF_KEYS: 0, NUMBER_OF_KEYS: 0,
@@ -222,7 +223,7 @@ describe('Client', () => {
}); });
}); });
describe('multi', () => { describe.only('multi', () => {
itWithClient(TestRedisServers.OPEN, 'simple', async client => { itWithClient(TestRedisServers.OPEN, 'simple', async client => {
assert.deepEqual( assert.deepEqual(
await client.multi() await client.multi()
@@ -268,6 +269,25 @@ describe('Client', () => {
await client.disconnect(); await client.disconnect();
} }
}); });
itWithClient(TestRedisServers.OPEN, 'WatchError', async client => {
await client.watch('key');
await client.set(
RedisClient.commandOptions({
isolated: true
}),
'key',
'1'
);
await assert.rejects(
client.multi()
.decr('key')
.exec(),
WatchError
);
});
}); });
it('scripts', async () => { it('scripts', async () => {

View File

@@ -47,7 +47,7 @@ describe('Multi Command', () => {
it('WatchError', async () => { it('WatchError', async () => {
assert.rejects( assert.rejects(
RedisMultiCommand.create(() => Promise.resolve(null)).exec(), RedisMultiCommand.create(() => Promise.resolve([null])).exec(),
WatchError WatchError
); );
}); });

View File

@@ -29,7 +29,7 @@ export interface MultiQueuedCommand {
transformReply?: RedisCommand['transformReply']; transformReply?: RedisCommand['transformReply'];
} }
export type RedisMultiExecutor = (queue: Array<MultiQueuedCommand>, chainId?: symbol) => Promise<null | Array<RedisReply>>; export type RedisMultiExecutor = (queue: Array<MultiQueuedCommand>, chainId?: symbol) => Promise<Array<RedisReply>>;
export default class RedisMultiCommand<M extends RedisModules = RedisModules, S extends RedisLuaScripts = RedisLuaScripts> { export default class RedisMultiCommand<M extends RedisModules = RedisModules, S extends RedisLuaScripts = RedisLuaScripts> {
static commandsExecutor(this: RedisMultiCommand, command: RedisCommand, args: Array<unknown>): RedisMultiCommand { static commandsExecutor(this: RedisMultiCommand, command: RedisCommand, args: Array<unknown>): RedisMultiCommand {
@@ -169,22 +169,22 @@ export default class RedisMultiCommand<M extends RedisModules = RedisModules, S
} }
const queue = this.#queue.splice(0), const queue = this.#queue.splice(0),
rawReplies = this.#handleNullReply( rawReplies = await this.#executor([
await this.#executor([ {
{ encodedCommand: encodeCommand(['MULTI'])
encodedCommand: encodeCommand(['MULTI']) },
}, ...queue,
...queue, {
{ encodedCommand: encodeCommand(['EXEC'])
encodedCommand: encodeCommand(['EXEC']) }
} ], Symbol('[RedisMultiCommand] Chain ID')),
], Symbol('[RedisMultiCommand] Chain ID')) execReply = rawReplies[rawReplies.length - 1] as (null | Array<RedisReply>);
);
return this.#transformReplies( if (execReply === null) {
rawReplies[rawReplies.length - 1] as Array<RedisReply>, throw new WatchError();
queue }
);
return this.#transformReplies(execReply, queue);
} }
async execAsPipeline(): Promise<Array<RedisReply>> { async execAsPipeline(): Promise<Array<RedisReply>> {
@@ -194,19 +194,11 @@ export default class RedisMultiCommand<M extends RedisModules = RedisModules, S
const queue = this.#queue.splice(0); const queue = this.#queue.splice(0);
return this.#transformReplies( return this.#transformReplies(
this.#handleNullReply(await this.#executor(queue)), await this.#executor(queue),
queue queue
); );
} }
#handleNullReply<T>(reply: null | T): T {
if (reply === null) {
throw new WatchError();
}
return reply;
}
#transformReplies(rawReplies: Array<RedisReply>, queue: Array<MultiQueuedCommand>): Array<RedisReply> { #transformReplies(rawReplies: Array<RedisReply>, queue: Array<MultiQueuedCommand>): Array<RedisReply> {
return rawReplies.map((reply, i) => { return rawReplies.map((reply, i) => {
const { transformReply, preservedArguments } = queue[i]; const { transformReply, preservedArguments } = queue[i];