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

"typed" multi

This commit is contained in:
Leibale
2023-04-25 09:48:11 -04:00
parent b272f18818
commit 567ae381b0
2 changed files with 28 additions and 22 deletions

View File

@@ -21,20 +21,15 @@ client.withFlags({
}).hGetAll('key'); // Map<string, Buffer> }).hGetAll('key'); // Map<string, Buffer>
``` ```
# `Multi.exec<'typed'>` # `multi.exec<'typed'>` / `multi.execTyped`
We have introduced the ability to perform a 'typed' `MULTI`/`EXEC` transaction. Rather than returning `Array<ReplyUnion>`, a transaction invoked with `.exec<'typed'>` will return types appropriate to the commands in the transaction where possible. We have introduced the ability to perform a "typed" `MULTI`/`EXEC` transaction. Rather than returning `Array<ReplyUnion>`, a transaction invoked with `.exec<'typed'>` will return types appropriate to the commands in the transaction where possible:
Example:
```javascript ```javascript
client.multi() const multi = client.multi().ping();
.ping() await multi.exec(); // Array<ReplyUnion>
.exec(); // Array<ReplyUnion> await multi.exec<'typed'>(); // [string]
await multi.execTyped(); // [string]
client.multi()
.ping()
.exec<'typed'>(); // [string]
``` ```
# Request & Reply Policies # Request & Reply Policies

View File

@@ -83,10 +83,14 @@ export type RedisClientMultiCommandType<
WithScripts<REPLIES, M, F, S, RESP, FLAGS> WithScripts<REPLIES, M, F, S, RESP, FLAGS>
); );
type ReplyType< type MULTI_REPLY = {
REPLIES, GENERIC: 'generic';
T = 'generic' TYPED: 'typed';
> = T extends 'typed' ? REPLIES : Array<ReplyUnion>; };
type MultiReply = MULTI_REPLY[keyof MULTI_REPLY];
type ReplyType<T extends MultiReply, REPLIES> = T extends MULTI_REPLY['TYPED'] ? REPLIES : Array<ReplyUnion>;
export type RedisClientMultiExecutor = ( export type RedisClientMultiExecutor = (
queue: Array<RedisMultiQueuedCommand>, queue: Array<RedisMultiQueuedCommand>,
@@ -144,8 +148,7 @@ export default class RedisClientMultiCommand<REPLIES = []> extends RedisMultiCom
M extends RedisModules = Record<string, never>, M extends RedisModules = Record<string, never>,
F extends RedisFunctions = Record<string, never>, F extends RedisFunctions = Record<string, never>,
S extends RedisScripts = Record<string, never>, S extends RedisScripts = Record<string, never>,
RESP extends RespVersions = 2, RESP extends RespVersions = 2
FLAGS extends Flags = {}
>(config?: CommanderConfig<M, F, S, RESP>) { >(config?: CommanderConfig<M, F, S, RESP>) {
return attachConfig({ return attachConfig({
BaseClass: RedisClientMultiCommand, BaseClass: RedisClientMultiCommand,
@@ -221,7 +224,7 @@ export default class RedisClientMultiCommand<REPLIES = []> extends RedisMultiCom
select = this.SELECT; select = this.SELECT;
async exec<T>(execAsPipeline = false) { async exec<T extends MultiReply = MULTI_REPLY['GENERIC']>(execAsPipeline = false) {
if (execAsPipeline) return this.execAsPipeline<T>(); if (execAsPipeline) return this.execAsPipeline<T>();
return this.handleExecReplies( return this.handleExecReplies(
@@ -230,19 +233,27 @@ export default class RedisClientMultiCommand<REPLIES = []> extends RedisMultiCom
this.#selectedDB, this.#selectedDB,
RedisMultiCommand.generateChainId() RedisMultiCommand.generateChainId()
) )
) as ReplyType<REPLIES, T>; ) as ReplyType<T, REPLIES>;
} }
EXEC = this.exec; EXEC = this.exec;
async execAsPipeline<T>() { execTyped(execAsPipeline = false) {
if (this.queue.length === 0) return [] as ReplyType<REPLIES, T>; return this.exec<MULTI_REPLY['TYPED']>(execAsPipeline);
}
async execAsPipeline<T extends MultiReply = MULTI_REPLY['GENERIC']>() {
if (this.queue.length === 0) return [] as ReplyType<T, REPLIES>;
return this.transformReplies( return this.transformReplies(
await this.#executor( await this.#executor(
this.queue, this.queue,
this.#selectedDB this.#selectedDB
) )
) as ReplyType<REPLIES, T>; ) as ReplyType<T, REPLIES>;
}
execAsPipelineTyped() {
return this.execAsPipeline<MULTI_REPLY['TYPED']>();
} }
} }