1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-07 13:22:56 +03:00

Merge branch 'master' of github.com:redis/node-redis

This commit is contained in:
leibale
2022-06-30 13:38:29 -04:00
24 changed files with 1449 additions and 1468 deletions

View File

@@ -468,6 +468,20 @@ describe('Client', () => {
['PONG']
);
}, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('should remember selected db', async client => {
await client.multi()
.select(1)
.exec();
await killClient(client);
assert.equal(
(await client.clientInfo()).db,
1
);
}, {
...GLOBAL.SERVERS.OPEN,
minimumDockerVersion: [6, 2] // CLIENT INFO
});
});
testUtils.testWithClient('scripts', async client => {

View File

@@ -606,18 +606,26 @@ export default class RedisClient<
);
}
multiExecutor(commands: Array<RedisMultiQueuedCommand>, chainId?: symbol): Promise<Array<RedisCommandRawReply>> {
async multiExecutor(
commands: Array<RedisMultiQueuedCommand>,
selectedDB?: number,
chainId?: symbol
): Promise<Array<RedisCommandRawReply>> {
const promise = Promise.all(
commands.map(({ args }) => {
return this.#queue.addCommand(args, RedisClient.commandOptions({
chainId
}));
return this.#queue.addCommand(args, { chainId });
})
);
this.#tick();
return promise;
const results = await promise;
if (selectedDB !== undefined) {
this.#selectedDB = selectedDB;
}
return results;
}
async* scanIterator(options?: ScanCommandOptions): AsyncIterable<string> {

View File

@@ -58,13 +58,13 @@ type InstantiableRedisMultiCommand<
S extends RedisScripts
> = new (...args: ConstructorParameters<typeof RedisClientMultiCommand>) => RedisClientMultiCommandType<M, F, S>;
export type RedisClientMultiExecutor = (queue: Array<RedisMultiQueuedCommand>, chainId?: symbol) => Promise<Array<RedisCommandRawReply>>;
export type RedisClientMultiExecutor = (
queue: Array<RedisMultiQueuedCommand>,
selectedDB?: number,
chainId?: symbol
) => Promise<Array<RedisCommandRawReply>>;
export default class RedisClientMultiCommand {
readonly #multi = new RedisMultiCommand();
readonly #executor: RedisClientMultiExecutor;
static extend<
M extends RedisModules,
F extends RedisFunctions,
@@ -81,7 +81,10 @@ export default class RedisClientMultiCommand {
});
}
readonly #multi = new RedisMultiCommand();
readonly #executor: RedisClientMultiExecutor;
readonly v4: Record<string, any> = {};
#selectedDB?: number;
constructor(executor: RedisClientMultiExecutor, legacyMode = false) {
this.#executor = executor;
@@ -136,6 +139,13 @@ export default class RedisClientMultiCommand {
);
}
SELECT(db: number, transformReply?: RedisCommand['transformReply']): this {
this.#selectedDB = db;
return this.addCommand(['SELECT', db.toString()], transformReply);
}
select = this.SELECT;
addCommand(args: RedisCommandArguments, transformReply?: RedisCommand['transformReply']): this {
this.#multi.addCommand(args, transformReply);
return this;
@@ -160,7 +170,11 @@ export default class RedisClientMultiCommand {
if (!commands) return [];
return this.#multi.handleExecReplies(
await this.#executor(commands, RedisMultiCommand.generateChainId())
await this.#executor(
commands,
this.#selectedDB,
RedisMultiCommand.generateChainId()
)
);
}
@@ -168,7 +182,10 @@ export default class RedisClientMultiCommand {
async execAsPipeline(): Promise<Array<RedisCommandRawReply>> {
return this.#multi.transformReplies(
await this.#executor(this.#multi.queue)
await this.#executor(
this.#multi.queue,
this.#selectedDB
)
);
}
}

View File

@@ -230,7 +230,7 @@ export default class RedisCluster<
return this.#execute(
firstKey,
false,
client => client.multiExecutor(commands, chainId)
client => client.multiExecutor(commands, undefined, chainId)
);
},
routing

View File

@@ -41,11 +41,20 @@ describe('HSET', () => {
);
});
it('Object', () => {
assert.deepEqual(
transformArguments('key', { field: 'value' }),
['HSET', 'key', 'field', 'value']
);
describe('Object', () => {
it('string', () => {
assert.deepEqual(
transformArguments('key', { field: 'value' }),
['HSET', 'key', 'field', 'value']
);
});
it('Buffer', () => {
assert.deepEqual(
transformArguments('key', { field: Buffer.from('value') }),
['HSET', 'key', 'field', Buffer.from('value')]
);
});
});
});
@@ -62,4 +71,4 @@ describe('HSET', () => {
1
);
}, GLOBAL.CLUSTERS.OPEN);
});
});

View File

@@ -20,8 +20,10 @@ export function transformArguments(...[ key, value, fieldValue ]: SingleFieldArg
const args: RedisCommandArguments = ['HSET', key];
if (typeof value === 'string' || typeof value === 'number' || Buffer.isBuffer(value)) {
pushValue(args, value);
pushValue(args, fieldValue!);
args.push(
convertValue(value),
convertValue(fieldValue!)
);
} else if (value instanceof Map) {
pushMap(args, value);
} else if (Array.isArray(value)) {
@@ -35,8 +37,10 @@ export function transformArguments(...[ key, value, fieldValue ]: SingleFieldArg
function pushMap(args: RedisCommandArguments, map: HSETMap): void {
for (const [key, value] of map.entries()) {
pushValue(args, key);
pushValue(args, value);
args.push(
convertValue(key),
convertValue(value)
);
}
}
@@ -47,22 +51,23 @@ function pushTuples(args: RedisCommandArguments, tuples: HSETTuples): void {
continue;
}
pushValue(args, tuple);
args.push(convertValue(tuple));
}
}
function pushObject(args: RedisCommandArguments, object: HSETObject): void {
for (const key of Object.keys(object)) {
args.push(key.toString(), object[key].toString());
args.push(
convertValue(key),
convertValue(object[key])
);
}
}
function pushValue(args: RedisCommandArguments, value: Types): void {
args.push(
typeof value === 'number' ?
value.toString() :
value
);
function convertValue(value: Types): RedisCommandArgument {
return typeof value === 'number' ?
value.toString() :
value;
}
export declare function transformReply(): number;

View File

@@ -3,7 +3,7 @@ import { SinonSpy } from 'sinon';
import { promiseTimeout } from './utils';
export default new TestUtils({
defaultDockerVersion: '7.0-rc3',
defaultDockerVersion: '7.0.2',
dockerImageName: 'redis',
dockerImageVersionArgument: 'redis-version'
});

View File

@@ -21,19 +21,19 @@
"devDependencies": {
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@redis/test-utils": "*",
"@types/node": "^17.0.31",
"@types/sinon": "^10.0.11",
"@types/node": "^18.0.0",
"@types/sinon": "^10.0.12",
"@types/yallist": "^4.0.1",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"eslint": "^8.14.0",
"@typescript-eslint/eslint-plugin": "^5.30.0",
"@typescript-eslint/parser": "^5.30.0",
"eslint": "^8.18.0",
"nyc": "^15.1.0",
"release-it": "^15.0.0",
"sinon": "^13.0.2",
"release-it": "^15.1.1",
"sinon": "^14.0.0",
"source-map-support": "^0.5.21",
"ts-node": "^10.7.0",
"typedoc": "^0.22.15",
"typescript": "^4.6.4"
"ts-node": "^10.8.1",
"typedoc": "^0.23.2",
"typescript": "^4.7.4"
},
"engines": {
"node": ">=14"