You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-06 02:15:48 +03:00
ref #2370 add support for CommandIterator in ScanIterator
Co-authored-by: Leibale Eidelman <me@leibale.com>
This commit is contained in:
@@ -215,7 +215,7 @@ describe('Client', () => {
|
|||||||
|
|
||||||
testUtils.testWithClient('client.hGetAll should return object', async client => {
|
testUtils.testWithClient('client.hGetAll should return object', async client => {
|
||||||
await client.v4.hSet('key', 'field', 'value');
|
await client.v4.hSet('key', 'field', 'value');
|
||||||
|
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
await promisify(client.hGetAll).call(client, 'key'),
|
await promisify(client.hGetAll).call(client, 'key'),
|
||||||
Object.create(null, {
|
Object.create(null, {
|
||||||
@@ -317,7 +317,7 @@ describe('Client', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('client.multi.hGetAll should return object', async client => {
|
testUtils.testWithClient('client.multi.hGetAll should return object', async client => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
await multiExecAsync(
|
await multiExecAsync(
|
||||||
client.multi()
|
client.multi()
|
||||||
@@ -607,24 +607,48 @@ describe('Client', () => {
|
|||||||
return client.executeIsolated(isolated => killClient(isolated, client));
|
return client.executeIsolated(isolated => killClient(isolated, client));
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
|
|
||||||
testUtils.testWithClient('scanIterator', async client => {
|
describe('scanIterator', () => {
|
||||||
const promises = [],
|
testUtils.testWithClient('strings', async client => {
|
||||||
keys = new Set();
|
const args: Array<string> = [],
|
||||||
for (let i = 0; i < 100; i++) {
|
keys = new Set<string>();
|
||||||
const key = i.toString();
|
for (let i = 0; i < 100; i++) {
|
||||||
keys.add(key);
|
const key = i.toString();
|
||||||
promises.push(client.set(key, ''));
|
args.push(key, '');
|
||||||
}
|
keys.add(key);
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(promises);
|
await client.mSet(args);
|
||||||
|
|
||||||
const results = new Set();
|
const results = new Set<string>();
|
||||||
for await (const key of client.scanIterator()) {
|
for await (const key of client.scanIterator()) {
|
||||||
results.add(key);
|
results.add(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.deepEqual(keys, results);
|
assert.deepEqual(keys, results);
|
||||||
}, GLOBAL.SERVERS.OPEN);
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
|
|
||||||
|
testUtils.testWithClient('buffers', async client => {
|
||||||
|
const args: Array<string | Buffer> = [],
|
||||||
|
keys = new Set<Buffer>();
|
||||||
|
for (let i = 0; i < 100; i++) {
|
||||||
|
const key = Buffer.from([i]);
|
||||||
|
args.push(key, '');
|
||||||
|
keys.add(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.mSet(args);
|
||||||
|
|
||||||
|
const results = new Set<Buffer>(),
|
||||||
|
iteartor = client.scanIterator(
|
||||||
|
client.commandOptions({ returnBuffers: true })
|
||||||
|
);
|
||||||
|
for await (const key of iteartor) {
|
||||||
|
results.add(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.deepEqual(keys, results);
|
||||||
|
}, GLOBAL.SERVERS.OPEN);
|
||||||
|
});
|
||||||
|
|
||||||
testUtils.testWithClient('hScanIterator', async client => {
|
testUtils.testWithClient('hScanIterator', async client => {
|
||||||
const hash: Record<string, string> = {};
|
const hash: Record<string, string> = {};
|
||||||
|
@@ -415,7 +415,7 @@ export default class RedisClient<
|
|||||||
);
|
);
|
||||||
} else if (!this.#socket.isReady && this.#options?.disableOfflineQueue) {
|
} else if (!this.#socket.isReady && this.#options?.disableOfflineQueue) {
|
||||||
return Promise.reject(new ClientOfflineError());
|
return Promise.reject(new ClientOfflineError());
|
||||||
}
|
}
|
||||||
|
|
||||||
const promise = this.#queue.addCommand<T>(args, options);
|
const promise = this.#queue.addCommand<T>(args, options);
|
||||||
this.#tick();
|
this.#tick();
|
||||||
@@ -656,10 +656,29 @@ export default class RedisClient<
|
|||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
async* scanIterator(options?: ScanCommandOptions): AsyncIterable<string> {
|
scanIterator<T extends CommandOptions<ClientCommandOptions>>(
|
||||||
|
commandOptions: T,
|
||||||
|
options?: ScanCommandOptions
|
||||||
|
): AsyncIterable<T['returnBuffers'] extends true ? Buffer : string>;
|
||||||
|
scanIterator(
|
||||||
|
options?: ScanCommandOptions
|
||||||
|
): AsyncIterable<string>;
|
||||||
|
async* scanIterator<T extends CommandOptions<ClientCommandOptions>>(
|
||||||
|
commandOptions?: T | ScanCommandOptions,
|
||||||
|
options?: ScanCommandOptions
|
||||||
|
): AsyncIterable<T['returnBuffers'] extends true ? Buffer : string> {
|
||||||
|
if (!isCommandOptions(commandOptions)) {
|
||||||
|
options = commandOptions;
|
||||||
|
commandOptions = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const scan = commandOptions ?
|
||||||
|
(...args: Array<unknown>) => (this as any).scan(commandOptions, ...args) :
|
||||||
|
(...args: Array<unknown>) => (this as any).scan(...args);
|
||||||
|
|
||||||
let cursor = 0;
|
let cursor = 0;
|
||||||
do {
|
do {
|
||||||
const reply = await (this as any).scan(cursor, options);
|
const reply = await scan(cursor, options);
|
||||||
cursor = reply.cursor;
|
cursor = reply.cursor;
|
||||||
for (const key of reply.keys) {
|
for (const key of reply.keys) {
|
||||||
yield key;
|
yield key;
|
||||||
@@ -726,3 +745,15 @@ attachCommands({
|
|||||||
executor: RedisClient.prototype.commandsExecutor
|
executor: RedisClient.prototype.commandsExecutor
|
||||||
});
|
});
|
||||||
(RedisClient.prototype as any).Multi = RedisClientMultiCommand;
|
(RedisClient.prototype as any).Multi = RedisClientMultiCommand;
|
||||||
|
|
||||||
|
const client = RedisClient.create();
|
||||||
|
|
||||||
|
const a = client.scanIterator(
|
||||||
|
client.commandOptions({returnBuffers: true})
|
||||||
|
)
|
||||||
|
|
||||||
|
const b = client.scanIterator(
|
||||||
|
client.commandOptions({returnBuffers: false})
|
||||||
|
)
|
||||||
|
|
||||||
|
const c = client.scanIterator()
|
@@ -52,7 +52,7 @@ const DOCKER_FODLER_PATH = path.join(__dirname, '../docker');
|
|||||||
async function spawnRedisServerDocker({ image, version }: RedisServerDockerConfig, serverArguments: Array<string>): Promise<RedisServerDocker> {
|
async function spawnRedisServerDocker({ image, version }: RedisServerDockerConfig, serverArguments: Array<string>): Promise<RedisServerDocker> {
|
||||||
const port = (await portIterator.next()).value,
|
const port = (await portIterator.next()).value,
|
||||||
{ stdout, stderr } = await execAsync(
|
{ stdout, stderr } = await execAsync(
|
||||||
'docker run -d --network host $(' +
|
`docker run -d -p ${port}:${port} $(` +
|
||||||
`docker build ${DOCKER_FODLER_PATH} -q ` +
|
`docker build ${DOCKER_FODLER_PATH} -q ` +
|
||||||
`--build-arg IMAGE=${image}:${version} ` +
|
`--build-arg IMAGE=${image}:${version} ` +
|
||||||
`--build-arg REDIS_ARGUMENTS="--save '' --port ${port.toString()} ${serverArguments.join(' ')}"` +
|
`--build-arg REDIS_ARGUMENTS="--save '' --port ${port.toString()} ${serverArguments.join(' ')}"` +
|
||||||
|
Reference in New Issue
Block a user