You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-10 11:43:01 +03:00
fix client pubsub and uncomment tests
This commit is contained in:
@@ -211,9 +211,7 @@ export default class RedisCommandsQueue {
|
|||||||
signal.addEventListener('abort', value.abort.listener, { once: true });
|
signal.addEventListener('abort', value.abort.listener, { once: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
node = options?.asap ?
|
node = this._toWrite.add(value, options?.asap);
|
||||||
this._toWrite.unshift(value) :
|
|
||||||
this._toWrite.push(value);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,7 +270,7 @@ export default class RedisCommandsQueue {
|
|||||||
if (command === undefined) return;
|
if (command === undefined) return;
|
||||||
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
(asap ? this._toWrite.unshift : this._toWrite.push)({
|
this._toWrite.add({
|
||||||
args: command.args,
|
args: command.args,
|
||||||
chainId: undefined,
|
chainId: undefined,
|
||||||
abort: undefined,
|
abort: undefined,
|
||||||
@@ -287,7 +285,7 @@ export default class RedisCommandsQueue {
|
|||||||
},
|
},
|
||||||
channelsCounter: command.channelsCounter,
|
channelsCounter: command.channelsCounter,
|
||||||
typeMapping: PUSH_TYPE_MAPPING
|
typeMapping: PUSH_TYPE_MAPPING
|
||||||
});
|
}, asap);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -525,222 +525,217 @@ describe('Client', () => {
|
|||||||
assert.deepEqual(map, results);
|
assert.deepEqual(map, results);
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
|
|
||||||
// describe('PubSub', () => {
|
describe('PubSub', () => {
|
||||||
// testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => {
|
testUtils.testWithClient('should be able to publish and subscribe to messages', async publisher => {
|
||||||
// function assertStringListener(message: string, channel: string) {
|
function assertStringListener(message: string, channel: string) {
|
||||||
// assert.equal(typeof message, 'string');
|
assert.equal(typeof message, 'string');
|
||||||
// assert.equal(typeof channel, 'string');
|
assert.equal(typeof channel, 'string');
|
||||||
// }
|
}
|
||||||
|
|
||||||
// function assertBufferListener(message: Buffer, channel: Buffer) {
|
function assertBufferListener(message: Buffer, channel: Buffer) {
|
||||||
// assert.ok(message instanceof Buffer);
|
assert.ok(message instanceof Buffer);
|
||||||
// assert.ok(channel instanceof Buffer);
|
assert.ok(channel instanceof Buffer);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// const subscriber = publisher.duplicate();
|
const subscriber = await publisher.duplicate().connect();
|
||||||
|
|
||||||
// await subscriber.connect();
|
try {
|
||||||
|
const channelListener1 = spy(assertBufferListener),
|
||||||
|
channelListener2 = spy(assertStringListener),
|
||||||
|
patternListener = spy(assertStringListener);
|
||||||
|
|
||||||
// try {
|
await Promise.all([
|
||||||
// const channelListener1 = spy(assertBufferListener),
|
subscriber.subscribe('channel', channelListener1, true),
|
||||||
// channelListener2 = spy(assertStringListener),
|
subscriber.subscribe('channel', channelListener2),
|
||||||
// patternListener = spy(assertStringListener);
|
subscriber.pSubscribe('channel*', patternListener)
|
||||||
|
]);
|
||||||
|
await Promise.all([
|
||||||
|
waitTillBeenCalled(channelListener1),
|
||||||
|
waitTillBeenCalled(channelListener2),
|
||||||
|
waitTillBeenCalled(patternListener),
|
||||||
|
publisher.publish(Buffer.from('channel'), Buffer.from('message'))
|
||||||
|
]);
|
||||||
|
assert.ok(channelListener1.calledOnceWithExactly(Buffer.from('message'), Buffer.from('channel')));
|
||||||
|
assert.ok(channelListener2.calledOnceWithExactly('message', 'channel'));
|
||||||
|
assert.ok(patternListener.calledOnceWithExactly('message', 'channel'));
|
||||||
|
|
||||||
// await Promise.all([
|
await subscriber.unsubscribe('channel', channelListener1, true);
|
||||||
// subscriber.subscribe('channel', channelListener1, true),
|
await Promise.all([
|
||||||
// subscriber.subscribe('channel', channelListener2),
|
waitTillBeenCalled(channelListener2),
|
||||||
// subscriber.pSubscribe('channel*', patternListener)
|
waitTillBeenCalled(patternListener),
|
||||||
// ]);
|
publisher.publish('channel', 'message')
|
||||||
// await Promise.all([
|
]);
|
||||||
// waitTillBeenCalled(channelListener1),
|
assert.ok(channelListener1.calledOnce);
|
||||||
// waitTillBeenCalled(channelListener2),
|
assert.ok(channelListener2.calledTwice);
|
||||||
// waitTillBeenCalled(patternListener),
|
assert.ok(channelListener2.secondCall.calledWithExactly('message', 'channel'));
|
||||||
// publisher.publish(Buffer.from('channel'), Buffer.from('message'))
|
assert.ok(patternListener.calledTwice);
|
||||||
// ]);
|
assert.ok(patternListener.secondCall.calledWithExactly('message', 'channel'));
|
||||||
|
await subscriber.unsubscribe('channel');
|
||||||
|
await Promise.all([
|
||||||
|
waitTillBeenCalled(patternListener),
|
||||||
|
publisher.publish('channel', 'message')
|
||||||
|
]);
|
||||||
|
assert.ok(channelListener1.calledOnce);
|
||||||
|
assert.ok(channelListener2.calledTwice);
|
||||||
|
assert.ok(patternListener.calledThrice);
|
||||||
|
assert.ok(patternListener.thirdCall.calledWithExactly('message', 'channel'));
|
||||||
|
|
||||||
// assert.ok(channelListener1.calledOnceWithExactly(Buffer.from('message'), Buffer.from('channel')));
|
await subscriber.pUnsubscribe();
|
||||||
// assert.ok(channelListener2.calledOnceWithExactly('message', 'channel'));
|
await publisher.publish('channel', 'message');
|
||||||
// assert.ok(patternListener.calledOnceWithExactly('message', 'channel'));
|
assert.ok(channelListener1.calledOnce);
|
||||||
|
assert.ok(channelListener2.calledTwice);
|
||||||
|
assert.ok(patternListener.calledThrice);
|
||||||
|
|
||||||
// await subscriber.unsubscribe('channel', channelListener1, true);
|
// should be able to send commands when unsubsribed from all channels (see #1652)
|
||||||
// await Promise.all([
|
await assert.doesNotReject(subscriber.ping());
|
||||||
// waitTillBeenCalled(channelListener2),
|
} finally {
|
||||||
// waitTillBeenCalled(patternListener),
|
subscriber.destroy();
|
||||||
// publisher.publish('channel', 'message')
|
}
|
||||||
// ]);
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
// assert.ok(channelListener1.calledOnce);
|
|
||||||
// assert.ok(channelListener2.calledTwice);
|
|
||||||
// assert.ok(channelListener2.secondCall.calledWithExactly('message', 'channel'));
|
|
||||||
// assert.ok(patternListener.calledTwice);
|
|
||||||
// assert.ok(patternListener.secondCall.calledWithExactly('message', 'channel'));
|
|
||||||
// await subscriber.unsubscribe('channel');
|
|
||||||
// await Promise.all([
|
|
||||||
// waitTillBeenCalled(patternListener),
|
|
||||||
// publisher.publish('channel', 'message')
|
|
||||||
// ]);
|
|
||||||
// assert.ok(channelListener1.calledOnce);
|
|
||||||
// assert.ok(channelListener2.calledTwice);
|
|
||||||
// assert.ok(patternListener.calledThrice);
|
|
||||||
// assert.ok(patternListener.thirdCall.calledWithExactly('message', 'channel'));
|
|
||||||
// await subscriber.pUnsubscribe();
|
|
||||||
// await publisher.publish('channel', 'message');
|
|
||||||
// assert.ok(channelListener1.calledOnce);
|
|
||||||
// assert.ok(channelListener2.calledTwice);
|
|
||||||
// assert.ok(patternListener.calledThrice);
|
|
||||||
// // should be able to send commands when unsubsribed from all channels (see #1652)
|
|
||||||
// await assert.doesNotReject(subscriber.ping());
|
|
||||||
// } finally {
|
|
||||||
// await subscriber.disconnect();
|
|
||||||
// }
|
|
||||||
// }, GLOBAL.SERVERS.OPEN);
|
|
||||||
|
|
||||||
// testUtils.testWithClient('should resubscribe', async publisher => {
|
testUtils.testWithClient('should resubscribe', async publisher => {
|
||||||
// const subscriber = publisher.duplicate();
|
const subscriber = await publisher.duplicate().connect();
|
||||||
|
|
||||||
// await subscriber.connect();
|
try {
|
||||||
|
const channelListener = spy();
|
||||||
|
await subscriber.subscribe('channel', channelListener);
|
||||||
|
|
||||||
// try {
|
const patternListener = spy();
|
||||||
// const channelListener = spy();
|
await subscriber.pSubscribe('channe*', patternListener);
|
||||||
// await subscriber.subscribe('channel', channelListener);
|
|
||||||
|
|
||||||
// const patternListener = spy();
|
await Promise.all([
|
||||||
// await subscriber.pSubscribe('channe*', patternListener);
|
once(subscriber, 'error'),
|
||||||
|
publisher.clientKill({
|
||||||
|
filter: 'SKIPME',
|
||||||
|
skipMe: true
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
// await Promise.all([
|
await once(subscriber, 'ready');
|
||||||
// once(subscriber, 'error'),
|
|
||||||
// publisher.clientKill({
|
|
||||||
// filter: ClientKillFilters.SKIP_ME,
|
|
||||||
// skipMe: true
|
|
||||||
// })
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// await once(subscriber, 'ready');
|
await Promise.all([
|
||||||
|
waitTillBeenCalled(channelListener),
|
||||||
|
waitTillBeenCalled(patternListener),
|
||||||
|
publisher.publish('channel', 'message')
|
||||||
|
]);
|
||||||
|
} finally {
|
||||||
|
subscriber.destroy();
|
||||||
|
}
|
||||||
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
|
|
||||||
// await Promise.all([
|
testUtils.testWithClient('should not fail when message arrives right after subscribe', async publisher => {
|
||||||
// waitTillBeenCalled(channelListener),
|
const subscriber = await publisher.duplicate().connect();
|
||||||
// waitTillBeenCalled(patternListener),
|
|
||||||
// publisher.publish('channel', 'message')
|
|
||||||
// ]);
|
|
||||||
// } finally {
|
|
||||||
// await subscriber.disconnect();
|
|
||||||
// }
|
|
||||||
// }, GLOBAL.SERVERS.OPEN);
|
|
||||||
|
|
||||||
// testUtils.testWithClient('should not fail when message arrives right after subscribe', async publisher => {
|
try {
|
||||||
// const subscriber = publisher.duplicate();
|
await assert.doesNotReject(Promise.all([
|
||||||
|
subscriber.subscribe('channel', () => {
|
||||||
|
// noop
|
||||||
|
}),
|
||||||
|
publisher.publish('channel', 'message')
|
||||||
|
]));
|
||||||
|
} finally {
|
||||||
|
subscriber.destroy();
|
||||||
|
}
|
||||||
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
|
|
||||||
// await subscriber.connect();
|
testUtils.testWithClient('should be able to quit in PubSub mode', async client => {
|
||||||
|
await client.subscribe('channel', () => {
|
||||||
|
// noop
|
||||||
|
});
|
||||||
|
|
||||||
// try {
|
await assert.doesNotReject(client.quit());
|
||||||
// await assert.doesNotReject(Promise.all([
|
|
||||||
// subscriber.subscribe('channel', () => {
|
|
||||||
// // noop
|
|
||||||
// }),
|
|
||||||
// publisher.publish('channel', 'message')
|
|
||||||
// ]));
|
|
||||||
// } finally {
|
|
||||||
// await subscriber.disconnect();
|
|
||||||
// }
|
|
||||||
// }, GLOBAL.SERVERS.OPEN);
|
|
||||||
|
|
||||||
// testUtils.testWithClient('should be able to quit in PubSub mode', async client => {
|
assert.equal(client.isOpen, false);
|
||||||
// await client.subscribe('channel', () => {
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
// // noop
|
});
|
||||||
// });
|
|
||||||
|
|
||||||
// await assert.doesNotReject(client.quit());
|
testUtils.testWithClient('ConnectionTimeoutError', async client => {
|
||||||
|
const promise = assert.rejects(client.connect(), ConnectionTimeoutError),
|
||||||
|
start = process.hrtime.bigint();
|
||||||
|
|
||||||
// assert.equal(client.isOpen, false);
|
while (process.hrtime.bigint() - start < 1_000_000) {
|
||||||
// }, GLOBAL.SERVERS.OPEN);
|
// block the event loop for 1ms, to make sure the connection will timeout
|
||||||
// });
|
}
|
||||||
|
|
||||||
// testUtils.testWithClient('ConnectionTimeoutError', async client => {
|
await promise;
|
||||||
// const promise = assert.rejects(client.connect(), ConnectionTimeoutError),
|
}, {
|
||||||
// start = process.hrtime.bigint();
|
...GLOBAL.SERVERS.OPEN,
|
||||||
|
clientOptions: {
|
||||||
|
socket: {
|
||||||
|
connectTimeout: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disableClientSetup: true
|
||||||
|
});
|
||||||
|
|
||||||
// while (process.hrtime.bigint() - start < 1_000_000) {
|
testUtils.testWithClient('client.quit', async client => {
|
||||||
// // block the event loop for 1ms, to make sure the connection will timeout
|
await client.connect();
|
||||||
// }
|
|
||||||
|
|
||||||
// await promise;
|
const pingPromise = client.ping(),
|
||||||
// }, {
|
quitPromise = client.quit();
|
||||||
// ...GLOBAL.SERVERS.OPEN,
|
assert.equal(client.isOpen, false);
|
||||||
// clientOptions: {
|
|
||||||
// socket: {
|
|
||||||
// connectTimeout: 1
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// disableClientSetup: true
|
|
||||||
// });
|
|
||||||
|
|
||||||
// testUtils.testWithClient('client.quit', async client => {
|
const [ping, quit] = await Promise.all([
|
||||||
// await client.connect();
|
pingPromise,
|
||||||
|
quitPromise,
|
||||||
|
assert.rejects(client.ping(), ClientClosedError)
|
||||||
|
]);
|
||||||
|
|
||||||
// const pingPromise = client.ping(),
|
assert.equal(ping, 'PONG');
|
||||||
// quitPromise = client.quit();
|
assert.equal(quit, 'OK');
|
||||||
// assert.equal(client.isOpen, false);
|
}, {
|
||||||
|
...GLOBAL.SERVERS.OPEN,
|
||||||
|
disableClientSetup: true
|
||||||
|
});
|
||||||
|
|
||||||
// const [ping, quit] = await Promise.all([
|
testUtils.testWithClient('client.disconnect', async client => {
|
||||||
// pingPromise,
|
const pingPromise = client.ping(),
|
||||||
// quitPromise,
|
disconnectPromise = client.disconnect();
|
||||||
// assert.rejects(client.ping(), ClientClosedError)
|
assert.equal(client.isOpen, false);
|
||||||
// ]);
|
await Promise.all([
|
||||||
|
assert.rejects(pingPromise, DisconnectsClientError),
|
||||||
|
assert.doesNotReject(disconnectPromise),
|
||||||
|
assert.rejects(client.ping(), ClientClosedError)
|
||||||
|
]);
|
||||||
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
|
|
||||||
// assert.equal(ping, 'PONG');
|
testUtils.testWithClient('should be able to connect after disconnect (see #1801)', async client => {
|
||||||
// assert.equal(quit, 'OK');
|
await client.disconnect();
|
||||||
// }, {
|
await client.connect();
|
||||||
// ...GLOBAL.SERVERS.OPEN,
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
// disableClientSetup: true
|
|
||||||
// });
|
|
||||||
|
|
||||||
// testUtils.testWithClient('client.disconnect', async client => {
|
testUtils.testWithClient('should be able to use ref and unref', client => {
|
||||||
// const pingPromise = client.ping(),
|
client.unref();
|
||||||
// disconnectPromise = client.disconnect();
|
client.ref();
|
||||||
// assert.equal(client.isOpen, false);
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
// await Promise.all([
|
|
||||||
// assert.rejects(pingPromise, DisconnectsClientError),
|
|
||||||
// assert.doesNotReject(disconnectPromise),
|
|
||||||
// assert.rejects(client.ping(), ClientClosedError)
|
|
||||||
// ]);
|
|
||||||
// }, GLOBAL.SERVERS.OPEN);
|
|
||||||
|
|
||||||
// testUtils.testWithClient('should be able to connect after disconnect (see #1801)', async client => {
|
testUtils.testWithClient('pingInterval', async client => {
|
||||||
// await client.disconnect();
|
assert.deepEqual(
|
||||||
// await client.connect();
|
await once(client, 'ping-interval'),
|
||||||
// }, GLOBAL.SERVERS.OPEN);
|
['PONG']
|
||||||
|
);
|
||||||
|
}, {
|
||||||
|
...GLOBAL.SERVERS.OPEN,
|
||||||
|
clientOptions: {
|
||||||
|
pingInterval: 1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// testUtils.testWithClient('should be able to use ref and unref', client => {
|
testUtils.testWithClient('should reject commands in connect phase when `disableOfflineQueue`', async client => {
|
||||||
// client.unref();
|
const connectPromise = client.connect();
|
||||||
// client.ref();
|
await assert.rejects(
|
||||||
// }, GLOBAL.SERVERS.OPEN);
|
client.ping(),
|
||||||
|
ClientOfflineError
|
||||||
// testUtils.testWithClient('pingInterval', async client => {
|
);
|
||||||
// assert.deepEqual(
|
await connectPromise;
|
||||||
// await once(client, 'ping-interval'),
|
await client.disconnect();
|
||||||
// ['PONG']
|
}, {
|
||||||
// );
|
...GLOBAL.SERVERS.OPEN,
|
||||||
// }, {
|
clientOptions: {
|
||||||
// ...GLOBAL.SERVERS.OPEN,
|
disableOfflineQueue: true
|
||||||
// clientOptions: {
|
},
|
||||||
// pingInterval: 1
|
disableClientSetup: true
|
||||||
// }
|
});
|
||||||
// });
|
|
||||||
|
|
||||||
// testUtils.testWithClient('should reject commands in connect phase when `disableOfflineQueue`', async client => {
|
|
||||||
// const connectPromise = client.connect();
|
|
||||||
// await assert.rejects(
|
|
||||||
// client.ping(),
|
|
||||||
// ClientOfflineError
|
|
||||||
// );
|
|
||||||
// await connectPromise;
|
|
||||||
// await client.disconnect();
|
|
||||||
// }, {
|
|
||||||
// ...GLOBAL.SERVERS.OPEN,
|
|
||||||
// clientOptions: {
|
|
||||||
// disableOfflineQueue: true
|
|
||||||
// },
|
|
||||||
// disableClientSetup: true
|
|
||||||
// });
|
|
||||||
|
|
||||||
describe('MONITOR', () => {
|
describe('MONITOR', () => {
|
||||||
testUtils.testWithClient('should be able to monitor commands', async client => {
|
testUtils.testWithClient('should be able to monitor commands', async client => {
|
||||||
|
@@ -59,6 +59,12 @@ export class DoublyLinkedList<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add(value: T, prepend = false) {
|
||||||
|
return prepend ?
|
||||||
|
this.unshift(value) :
|
||||||
|
this.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
shift() {
|
shift() {
|
||||||
if (this._head === undefined) return undefined;
|
if (this._head === undefined) return undefined;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user