You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
fix client.reset
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { SinglyLinkedList, DoublyLinkedNode, DoublyLinkedList } from './linked-list';
|
import { SinglyLinkedList, DoublyLinkedNode, DoublyLinkedList } from './linked-list';
|
||||||
import encodeCommand from '../RESP/encoder';
|
import encodeCommand from '../RESP/encoder';
|
||||||
import { Decoder, PUSH_TYPE_MAPPING, RESP_TYPES } from '../RESP/decoder';
|
import { Decoder, PUSH_TYPE_MAPPING, RESP_TYPES } from '../RESP/decoder';
|
||||||
import { CommandArguments, TypeMapping, ReplyUnion, RespVersions, SimpleStringReply, ReplyWithTypeMapping } from '../RESP/types';
|
import { CommandArguments, TypeMapping, ReplyUnion, RespVersions } from '../RESP/types';
|
||||||
import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub';
|
import { ChannelListeners, PubSub, PubSubCommand, PubSubListener, PubSubType, PubSubTypeListeners } from './pub-sub';
|
||||||
import { AbortError, ErrorReply } from '../errors';
|
import { AbortError, ErrorReply } from '../errors';
|
||||||
import { MonitorCallback } from '.';
|
import { MonitorCallback } from '.';
|
||||||
@@ -154,11 +154,11 @@ export default class RedisCommandsQueue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#addPubSubCommand(command: PubSubCommand, asap = false) {
|
#addPubSubCommand(command: PubSubCommand, asap = false, chainId?: symbol) {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
this.#toWrite.add({
|
this.#toWrite.add({
|
||||||
args: command.args,
|
args: command.args,
|
||||||
chainId: undefined,
|
chainId,
|
||||||
abort: undefined,
|
abort: undefined,
|
||||||
resolve() {
|
resolve() {
|
||||||
command.resolve();
|
command.resolve();
|
||||||
@@ -237,13 +237,13 @@ export default class RedisCommandsQueue {
|
|||||||
return this.#addPubSubCommand(command);
|
return this.#addPubSubCommand(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
resubscribe() {
|
resubscribe(chainId?: symbol) {
|
||||||
const commands = this.#pubSub.resubscribe();
|
const commands = this.#pubSub.resubscribe();
|
||||||
if (!commands.length) return;
|
if (!commands.length) return;
|
||||||
|
|
||||||
this.#setupPubSubHandler();
|
this.#setupPubSubHandler();
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
commands.map(command => this.#addPubSubCommand(command, true))
|
commands.map(command => this.#addPubSubCommand(command, true, chainId))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,11 +271,12 @@ export default class RedisCommandsQueue {
|
|||||||
return this.#pubSub.getTypeListeners(type);
|
return this.#pubSub.getTypeListeners(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
monitor(callback: MonitorCallback, typeMapping: TypeMapping = {}, asap = false) {
|
monitor(callback: MonitorCallback, options?: CommandOptions) {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
const typeMapping = options?.typeMapping ?? {};
|
||||||
this.#toWrite.add({
|
this.#toWrite.add({
|
||||||
args: ['MONITOR'],
|
args: ['MONITOR'],
|
||||||
chainId: undefined,
|
chainId: options?.chainId,
|
||||||
abort: undefined,
|
abort: undefined,
|
||||||
// using `resolve` instead of using `.then`/`await` to make sure it'll be called before processing the next reply
|
// using `resolve` instead of using `.then`/`await` to make sure it'll be called before processing the next reply
|
||||||
resolve: () => {
|
resolve: () => {
|
||||||
@@ -295,7 +296,7 @@ export default class RedisCommandsQueue {
|
|||||||
reject,
|
reject,
|
||||||
channelsCounter: undefined,
|
channelsCounter: undefined,
|
||||||
typeMapping
|
typeMapping
|
||||||
}, asap);
|
}, options?.asap);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +307,7 @@ export default class RedisCommandsQueue {
|
|||||||
|
|
||||||
#resetFallbackOnReply?: Decoder['onReply'];
|
#resetFallbackOnReply?: Decoder['onReply'];
|
||||||
|
|
||||||
async reset<T extends TypeMapping>(typeMapping?: T) {
|
async reset<T extends TypeMapping>(chainId: symbol, typeMapping?: T) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// overriding onReply to handle `RESET` while in `MONITOR` or PubSub mode
|
// overriding onReply to handle `RESET` while in `MONITOR` or PubSub mode
|
||||||
this.#resetFallbackOnReply = this.decoder.onReply;
|
this.#resetFallbackOnReply = this.decoder.onReply;
|
||||||
@@ -328,7 +329,7 @@ export default class RedisCommandsQueue {
|
|||||||
|
|
||||||
this.#toWrite.push({
|
this.#toWrite.push({
|
||||||
args: ['RESET'],
|
args: ['RESET'],
|
||||||
chainId: undefined,
|
chainId,
|
||||||
abort: undefined,
|
abort: undefined,
|
||||||
resolve,
|
resolve,
|
||||||
reject,
|
reject,
|
||||||
|
@@ -732,6 +732,9 @@ describe('Client', () => {
|
|||||||
skipMe: true
|
skipMe: true
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
await once(duplicate, 'ready');
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
waitTillBeenCalled(listener),
|
waitTillBeenCalled(listener),
|
||||||
client.ping()
|
client.ping()
|
||||||
|
@@ -332,24 +332,8 @@ export default class RedisClient<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#handshake(asap = false, promises: Array<Promise<unknown>> = []) {
|
#handshake(selectedDB: number) {
|
||||||
if (this.#selectedDB !== 0) {
|
const commands = [];
|
||||||
promises.push(
|
|
||||||
this.#queue.addCommand(
|
|
||||||
['SELECT', this.#selectedDB.toString()],
|
|
||||||
{ asap }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.#options?.readonly) {
|
|
||||||
promises.push(
|
|
||||||
this.#queue.addCommand(
|
|
||||||
COMMANDS.READONLY.transformArguments(),
|
|
||||||
{ asap }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.#options?.RESP) {
|
if (this.#options?.RESP) {
|
||||||
const hello: HelloOptions = {};
|
const hello: HelloOptions = {};
|
||||||
@@ -365,43 +349,45 @@ export default class RedisClient<
|
|||||||
hello.SETNAME = this.#options.name;
|
hello.SETNAME = this.#options.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
promises.push(
|
commands.push(
|
||||||
this.#queue.addCommand(
|
HELLO.transformArguments(this.#options.RESP, hello)
|
||||||
HELLO.transformArguments(this.#options.RESP, hello),
|
|
||||||
{ asap }
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (this.#options?.name) {
|
|
||||||
promises.push(
|
|
||||||
this.#queue.addCommand(
|
|
||||||
COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name),
|
|
||||||
{ asap }
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.#options?.username || this.#options?.password) {
|
if (this.#options?.username || this.#options?.password) {
|
||||||
promises.push(
|
commands.push(
|
||||||
this.#queue.addCommand(
|
|
||||||
COMMANDS.AUTH.transformArguments({
|
COMMANDS.AUTH.transformArguments({
|
||||||
username: this.#options.username,
|
username: this.#options.username,
|
||||||
password: this.#options.password ?? ''
|
password: this.#options.password ?? ''
|
||||||
}),
|
})
|
||||||
{ asap }
|
);
|
||||||
)
|
}
|
||||||
|
|
||||||
|
if (this.#options?.name) {
|
||||||
|
commands.push(
|
||||||
|
COMMANDS.CLIENT_SETNAME.transformArguments(this.#options.name)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return promises;
|
if (selectedDB !== 0) {
|
||||||
|
commands.push(['SELECT', this.#selectedDB.toString()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.#options?.readonly) {
|
||||||
|
commands.push(
|
||||||
|
COMMANDS.READONLY.transformArguments()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
#initiateSocket(): RedisSocket {
|
#initiateSocket(): RedisSocket {
|
||||||
const socketInitiator = () => {
|
const socketInitiator = () => {
|
||||||
const promises: Array<Promise<unknown>> = [];
|
const promises = [],
|
||||||
|
chainId = Symbol('Socket Initiator');
|
||||||
|
|
||||||
const resubscribePromise = this.#queue.resubscribe();
|
const resubscribePromise = this.#queue.resubscribe(chainId);
|
||||||
if (resubscribePromise) {
|
if (resubscribePromise) {
|
||||||
promises.push(resubscribePromise);
|
promises.push(resubscribePromise);
|
||||||
}
|
}
|
||||||
@@ -410,13 +396,24 @@ export default class RedisClient<
|
|||||||
promises.push(
|
promises.push(
|
||||||
this.#queue.monitor(
|
this.#queue.monitor(
|
||||||
this.#monitorCallback,
|
this.#monitorCallback,
|
||||||
this._commandOptions?.typeMapping,
|
{
|
||||||
true
|
typeMapping: this._commandOptions?.typeMapping,
|
||||||
|
chainId,
|
||||||
|
asap: true
|
||||||
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#handshake(true, promises);
|
const commands = this.#handshake(this.#selectedDB);
|
||||||
|
for (let i = commands.length - 1; i >= 0; --i) {
|
||||||
|
promises.push(
|
||||||
|
this.#queue.addCommand(commands[i], {
|
||||||
|
chainId,
|
||||||
|
asap: true
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (promises.length) {
|
if (promises.length) {
|
||||||
this.#write();
|
this.#write();
|
||||||
@@ -885,7 +882,9 @@ export default class RedisClient<
|
|||||||
}
|
}
|
||||||
|
|
||||||
async MONITOR(callback: MonitorCallback<TYPE_MAPPING>) {
|
async MONITOR(callback: MonitorCallback<TYPE_MAPPING>) {
|
||||||
const promise = this._self.#queue.monitor(callback, this._commandOptions?.typeMapping);
|
const promise = this._self.#queue.monitor(callback, {
|
||||||
|
typeMapping: this._commandOptions?.typeMapping
|
||||||
|
});
|
||||||
this._self.#scheduleWrite();
|
this._self.#scheduleWrite();
|
||||||
await promise;
|
await promise;
|
||||||
this._self.#monitorCallback = callback;
|
this._self.#monitorCallback = callback;
|
||||||
@@ -897,10 +896,20 @@ export default class RedisClient<
|
|||||||
* Reset the client to its default state (i.e. stop PubSub, stop monitoring, select default DB, etc.)
|
* Reset the client to its default state (i.e. stop PubSub, stop monitoring, select default DB, etc.)
|
||||||
*/
|
*/
|
||||||
async reset() {
|
async reset() {
|
||||||
const promises = [this._self.#queue.reset()];
|
const chainId = Symbol('Reset Chain'),
|
||||||
this._self.#handshake(false, promises);
|
promises = [this._self.#queue.reset(chainId)],
|
||||||
|
selectedDB = this._self.#options?.database ?? 0;
|
||||||
|
for (const command of this._self.#handshake(selectedDB)) {
|
||||||
|
promises.push(
|
||||||
|
this._self.#queue.addCommand(command, {
|
||||||
|
chainId
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
this._self.#scheduleWrite();
|
this._self.#scheduleWrite();
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
|
this._self.#selectedDB = selectedDB;
|
||||||
|
this._self.#monitorCallback = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user