1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-09 00:22:08 +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 { itWithClient, TEST_REDIS_SERVERS, TestRedisServers, waitTillBeenCalled, isRedisVersionGreaterThan } from './test-utils';
import RedisClient from './client';
import { AbortError } from './errors';
import { AbortError, WatchError } from './errors';
import { defineScript } from './lua-script';
import { spy } from 'sinon';
import { commandOptions } from './command-options';
export const SQUARE_SCRIPT = defineScript({
NUMBER_OF_KEYS: 0,
@@ -222,7 +223,7 @@ describe('Client', () => {
});
});
describe('multi', () => {
describe.only('multi', () => {
itWithClient(TestRedisServers.OPEN, 'simple', async client => {
assert.deepEqual(
await client.multi()
@@ -268,6 +269,25 @@ describe('Client', () => {
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 () => {

View File

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

View File

@@ -29,7 +29,7 @@ export interface MultiQueuedCommand {
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> {
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),
rawReplies = this.#handleNullReply(
await this.#executor([
{
encodedCommand: encodeCommand(['MULTI'])
},
...queue,
{
encodedCommand: encodeCommand(['EXEC'])
}
], Symbol('[RedisMultiCommand] Chain ID'))
);
rawReplies = await this.#executor([
{
encodedCommand: encodeCommand(['MULTI'])
},
...queue,
{
encodedCommand: encodeCommand(['EXEC'])
}
], Symbol('[RedisMultiCommand] Chain ID')),
execReply = rawReplies[rawReplies.length - 1] as (null | Array<RedisReply>);
return this.#transformReplies(
rawReplies[rawReplies.length - 1] as Array<RedisReply>,
queue
);
if (execReply === null) {
throw new WatchError();
}
return this.#transformReplies(execReply, queue);
}
async execAsPipeline(): Promise<Array<RedisReply>> {
@@ -194,19 +194,11 @@ export default class RedisMultiCommand<M extends RedisModules = RedisModules, S
const queue = this.#queue.splice(0);
return this.#transformReplies(
this.#handleNullReply(await this.#executor(queue)),
await this.#executor(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> {
return rawReplies.map((reply, i) => {
const { transformReply, preservedArguments } = queue[i];