You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
Merge branch 'v5' of github.com:leibale/node-redis into v5
This commit is contained in:
@@ -18,7 +18,7 @@ export default async (host) => {
|
||||
|
||||
return {
|
||||
benchmark() {
|
||||
return client.withFlags({}).module.ping();
|
||||
return client.withTypeMapping({}).module.ping();
|
||||
},
|
||||
teardown() {
|
||||
return client.disconnect();
|
||||
|
10
docs/todo.md
10
docs/todo.md
@@ -1,3 +1,13 @@
|
||||
# Leibale
|
||||
|
||||
- Does `close`/`destory` actually close the connection from the Redis POV? Works with OSS, but what about Redis Enterprie?
|
||||
|
||||
# Docs
|
||||
|
||||
- [v4 to v5](./v4-to-v5.md) - Legacy mode
|
||||
- [Command Options](./command-options.md)
|
||||
- [RESP](./RESP.md)
|
||||
|
||||
# Missing functionality
|
||||
|
||||
- `HEXISTS`: accepts one field only, should be the same as `EXISTS`
|
||||
|
@@ -1,84 +1,242 @@
|
||||
import { Pool, Options as PoolOptions, createPool } from 'generic-pool';
|
||||
import { RedisFunctions, RedisModules, RedisScripts, RespVersions } from '../RESP/types';
|
||||
import RedisClient, { RedisClientType, RedisClientOptions } from '.';
|
||||
import { EventEmitter } from 'events';
|
||||
// import COMMANDS from '../commands';
|
||||
// import { RedisFunctions, RedisModules, RedisScripts, RespVersions, TypeMapping } from '../RESP/types';
|
||||
// import RedisClient, { RedisClientType, RedisClientOptions, RedisClientExtensions } from '.';
|
||||
// import { EventEmitter } from 'events';
|
||||
// import { DoublyLinkedNode, DoublyLinkedList, SinglyLinkedList } from './linked-list';
|
||||
|
||||
type RedisClientPoolOptions<
|
||||
M extends RedisModules,
|
||||
F extends RedisFunctions,
|
||||
S extends RedisScripts,
|
||||
RESP extends RespVersions
|
||||
> = RedisClientOptions<M, F, S, RESP> & PoolOptions;
|
||||
// export type RedisPoolOptions = typeof RedisClientPool['_DEFAULTS'];
|
||||
|
||||
export class RedisClientPool<
|
||||
M extends RedisModules,
|
||||
F extends RedisFunctions,
|
||||
S extends RedisScripts,
|
||||
RESP extends RespVersions
|
||||
> extends EventEmitter {
|
||||
_pool: Pool<RedisClientType<M, F, S, RESP>>;
|
||||
// export type PoolTask<
|
||||
// M extends RedisModules,
|
||||
// F extends RedisFunctions,
|
||||
// S extends RedisScripts,
|
||||
// RESP extends RespVersions,
|
||||
// TYPE_MAPPING extends TypeMapping,
|
||||
// T = unknown
|
||||
// > = (client: RedisClientType<M, F, S, RESP, TYPE_MAPPING>) => T;
|
||||
|
||||
static fromClient<
|
||||
M extends RedisModules,
|
||||
F extends RedisFunctions,
|
||||
S extends RedisScripts,
|
||||
RESP extends RespVersions
|
||||
>(
|
||||
client: RedisClientType<M, F, S, RESP>,
|
||||
poolOptions?: PoolOptions
|
||||
) {
|
||||
return new RedisClientPool<M, F, S, RESP>(
|
||||
() => client.duplicate(),
|
||||
poolOptions
|
||||
);
|
||||
}
|
||||
// export type RedisClientPoolType<
|
||||
// M extends RedisModules = {},
|
||||
// F extends RedisFunctions = {},
|
||||
// S extends RedisScripts = {},
|
||||
// RESP extends RespVersions = 2,
|
||||
// TYPE_MAPPING extends TypeMapping = {}
|
||||
// > = (
|
||||
// RedisClientPool<M, F, S, RESP, TYPE_MAPPING> &
|
||||
// RedisClientExtensions<M, F, S, RESP, TYPE_MAPPING>
|
||||
// );
|
||||
|
||||
static fromOptions<
|
||||
M extends RedisModules,
|
||||
F extends RedisFunctions,
|
||||
S extends RedisScripts,
|
||||
RESP extends RespVersions
|
||||
>(
|
||||
options: RedisClientPoolOptions<M, F, S, RESP>,
|
||||
poolOptions?: PoolOptions
|
||||
) {
|
||||
return new RedisClientPool(
|
||||
RedisClient.factory(options),
|
||||
poolOptions
|
||||
);
|
||||
}
|
||||
// export class RedisClientPool<
|
||||
// M extends RedisModules = {},
|
||||
// F extends RedisFunctions = {},
|
||||
// S extends RedisScripts = {},
|
||||
// RESP extends RespVersions = 2,
|
||||
// TYPE_MAPPING extends TypeMapping = {}
|
||||
// > extends EventEmitter {
|
||||
// static fromClient<
|
||||
// M extends RedisModules,
|
||||
// F extends RedisFunctions,
|
||||
// S extends RedisScripts,
|
||||
// RESP extends RespVersions,
|
||||
// TYPE_MAPPING extends TypeMapping = {}
|
||||
// >(
|
||||
// client: RedisClientType<M, F, S, RESP, TYPE_MAPPING>,
|
||||
// poolOptions: Partial<RedisPoolOptions>
|
||||
// ) {
|
||||
// return RedisClientPool.create(
|
||||
// () => client.duplicate(),
|
||||
// poolOptions
|
||||
// );
|
||||
// }
|
||||
|
||||
constructor(
|
||||
clientFactory: () => RedisClientType<M, F, S, RESP>,
|
||||
options?: PoolOptions
|
||||
) {
|
||||
super();
|
||||
// static fromOptions<
|
||||
// M extends RedisModules,
|
||||
// F extends RedisFunctions,
|
||||
// S extends RedisScripts,
|
||||
// RESP extends RespVersions,
|
||||
// TYPE_MAPPING extends TypeMapping = {}
|
||||
// >(
|
||||
// options: RedisClientOptions<M, F, S, RESP, TYPE_MAPPING>,
|
||||
// poolOptions: Partial<RedisPoolOptions>
|
||||
// ) {
|
||||
// return RedisClientPool.create(
|
||||
// RedisClient.factory(options),
|
||||
// poolOptions
|
||||
// );
|
||||
// }
|
||||
|
||||
this._pool = createPool({
|
||||
create: async () => {
|
||||
const client = clientFactory();
|
||||
// static create<
|
||||
// M extends RedisModules,
|
||||
// F extends RedisFunctions,
|
||||
// S extends RedisScripts,
|
||||
// RESP extends RespVersions,
|
||||
// TYPE_MAPPING extends TypeMapping = {}
|
||||
// >(
|
||||
// clientFactory: () => RedisClientType<M, F, S, RESP, TYPE_MAPPING>,
|
||||
// options?: Partial<RedisPoolOptions>
|
||||
// ) {
|
||||
// return new RedisClientPool(
|
||||
// clientFactory,
|
||||
// options
|
||||
// ) as RedisClientPoolType<M, F, S, RESP, TYPE_MAPPING>;
|
||||
// }
|
||||
|
||||
// TODO: more events?
|
||||
client.on('error', (err: Error) => this.emit('error', err));
|
||||
// private static _DEFAULTS = {
|
||||
// /**
|
||||
// * The minimum number of clients to keep in the pool.
|
||||
// */
|
||||
// minimum: 0,
|
||||
// /**
|
||||
// * The maximum number of clients to keep in the pool.
|
||||
// */
|
||||
// maximum: 1,
|
||||
// /**
|
||||
// * The maximum time a task can wait for a client to become available.
|
||||
// */
|
||||
// acquireTimeout: 3000,
|
||||
// /**
|
||||
// * When there are `> minimum && < maximum` clients in the pool, the pool will wait for `cleanupDelay` milliseconds before closing the extra clients.
|
||||
// */
|
||||
// cleanupDelay: 3000
|
||||
// };
|
||||
|
||||
await client.connect();
|
||||
// private readonly _clientFactory: () => RedisClientType<M, F, S, RESP, TYPE_MAPPING>;
|
||||
// private readonly _options: Required<RedisPoolOptions>;
|
||||
// private readonly _idleClients = new SinglyLinkedList<RedisClientType<M, F, S, RESP, TYPE_MAPPING>>();
|
||||
// private readonly _usedClients = new DoublyLinkedList<RedisClientType<M, F, S, RESP, TYPE_MAPPING>>();
|
||||
// private readonly _tasksQueue = new SinglyLinkedList<{
|
||||
// resolve: <T>(value: T | PromiseLike<T>) => void;
|
||||
// reject: (reason?: unknown) => void;
|
||||
// fn: PoolTask<M, F, S, RESP, TYPE_MAPPING>;
|
||||
// }>();
|
||||
|
||||
return client;
|
||||
},
|
||||
// TODO: destroy has to return a Promise?!
|
||||
destroy: async client => client.disconnect()
|
||||
}, options);
|
||||
}
|
||||
// constructor(
|
||||
// clientFactory: () => RedisClientType<M, F, S, RESP, TYPE_MAPPING>,
|
||||
// options?: Partial<RedisPoolOptions>
|
||||
// ) {
|
||||
// super();
|
||||
|
||||
execute<T>(fn: () => T): Promise<T> {
|
||||
return this._pool.use(fn);
|
||||
}
|
||||
// this._clientFactory = clientFactory;
|
||||
// this._options = {
|
||||
// ...RedisClientPool._DEFAULTS,
|
||||
// ...options
|
||||
// };
|
||||
// this._initate();
|
||||
// }
|
||||
|
||||
close() {
|
||||
// TODO
|
||||
}
|
||||
// private async _initate() {
|
||||
// const promises = [];
|
||||
// while (promises.length < this._options.minimum) {
|
||||
// promises.push(this._create());
|
||||
// }
|
||||
|
||||
disconnect() {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
// try {
|
||||
// await Promise.all(promises);
|
||||
// } catch (err) {
|
||||
// this.destroy();
|
||||
// this.emit('error', err);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private async _create() {
|
||||
// const client = this._clientFactory()
|
||||
// // TODO: more events?
|
||||
// .on('error', (err: Error) => this.emit('error', err));
|
||||
|
||||
// const node = this._usedClients.push(client);
|
||||
|
||||
// await client.connect();
|
||||
|
||||
// this._usedClients.remove(node);
|
||||
|
||||
// return client;
|
||||
// }
|
||||
|
||||
// execute<T>(fn: PoolTask<M, F, S, RESP, TYPE_MAPPING, T>): Promise<T> {
|
||||
// return new Promise<T>((resolve, reject) => {
|
||||
// let client = this._idleClients.shift();
|
||||
// if (!client) {
|
||||
// this._tasksQueue.push({
|
||||
// // @ts-ignore
|
||||
// resolve,
|
||||
// reject,
|
||||
// fn
|
||||
// });
|
||||
|
||||
// if (this._idleClients.length + this._usedClients.length < this._options.maximum) {
|
||||
// this._create();
|
||||
// }
|
||||
|
||||
// return;
|
||||
// }
|
||||
|
||||
// const node = this._usedClients.push(client);
|
||||
// // @ts-ignore
|
||||
// this._executeTask(node, resolve, reject, fn);
|
||||
// });
|
||||
// }
|
||||
|
||||
// private _executeTask(
|
||||
// node: DoublyLinkedNode<RedisClientType<M, F, S, RESP, TYPE_MAPPING>>,
|
||||
// resolve: <T>(value: T | PromiseLike<T>) => void,
|
||||
// reject: (reason?: unknown) => void,
|
||||
// fn: PoolTask<M, F, S, RESP, TYPE_MAPPING>
|
||||
// ) {
|
||||
// const result = fn(node.value);
|
||||
// if (result instanceof Promise) {
|
||||
// result.then(resolve, reject);
|
||||
// result.finally(() => this._returnClient(node))
|
||||
// } else {
|
||||
// resolve(result);
|
||||
// this._returnClient(node);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private _returnClient(node: DoublyLinkedListNode<RedisClientType<M, F, S, RESP, TYPE_MAPPING>>) {
|
||||
// const task = this._tasksQueue.shift();
|
||||
// if (task) {
|
||||
// this._executeTask(node, task.resolve, task.reject, task.fn);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (this._idleClients.length >= this._options.minimum) {
|
||||
// node.client.destroy();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// this._usedClients.remove(node);
|
||||
// this._idleClients.push(node.client);
|
||||
// }
|
||||
|
||||
// async close() {
|
||||
// const promises = [];
|
||||
|
||||
// for (const client of this._idleClients) {
|
||||
// promises.push(client.close());
|
||||
// }
|
||||
|
||||
// this._idleClients.reset();
|
||||
|
||||
// for (const client of this._usedClients) {
|
||||
// promises.push(client.close());
|
||||
// }
|
||||
|
||||
// this._usedClients.reset();
|
||||
|
||||
// await Promise.all(promises);
|
||||
// }
|
||||
|
||||
// destroy() {
|
||||
// for (const client of this._idleClients) {
|
||||
// client.destroy();
|
||||
// }
|
||||
|
||||
// this._idleClients.reset();
|
||||
|
||||
// for (const client of this._usedClients) {
|
||||
// client.destroy();
|
||||
// }
|
||||
|
||||
// this._usedClients.reset();
|
||||
// }
|
||||
// }
|
||||
|
260
test.mjs
Normal file
260
test.mjs
Normal file
@@ -0,0 +1,260 @@
|
||||
// // // import { createClient } from './benchmark/node_modules/@redis/client/dist/index.js';
|
||||
// // // import Redis from './benchmark/node_modules/ioredis/built/index.js';
|
||||
// // // import { setTimeout } from 'node:timers/promises';
|
||||
|
||||
// // // const client = createClient();
|
||||
// // // client.on('error', err => console.error(err));
|
||||
|
||||
// // // await client.connect();
|
||||
|
||||
// // // const io = new Redis({
|
||||
// // // lazyConnect: true,
|
||||
// // // enableAutoPipelining: true
|
||||
// // // });
|
||||
// // // await io.connect();
|
||||
|
||||
// // // const TIMES = 1_000;
|
||||
|
||||
// // // while (true) {
|
||||
// // // await benchmark('redis', () => {
|
||||
// // // const promises = [];
|
||||
// // // for (let i = 0; i < TIMES; i++) {
|
||||
// // // promises.push(client.ping());
|
||||
// // // }
|
||||
|
||||
// // // return Promise.all(promises);
|
||||
// // // });
|
||||
|
||||
// // // await benchmark('ioredis', () => {
|
||||
// // // const promises = [];
|
||||
// // // for (let i = 0; i < TIMES; i++) {
|
||||
// // // promises.push(io.ping());
|
||||
// // // }
|
||||
|
||||
// // // return Promise.all(promises);
|
||||
// // // });
|
||||
// // // }
|
||||
|
||||
// // // async function benchmark(name, fn) {
|
||||
// // // const start = process.hrtime.bigint();
|
||||
|
||||
// // // await fn();
|
||||
|
||||
// // // const took = Number(process.hrtime.bigint() - start);
|
||||
// // // console.log(took, name);
|
||||
|
||||
// // // console.log('Sleep');
|
||||
// // // await setTimeout(1000);
|
||||
// // // console.log('Continue');
|
||||
// // // }
|
||||
|
||||
// import Redis from 'ioredis';
|
||||
|
||||
// const cluster = new Redis.Cluster([{
|
||||
// port: 6379,
|
||||
// host: "127.0.0.1",
|
||||
// }]);
|
||||
|
||||
// setInterval(() => {
|
||||
// let i = 0;
|
||||
// cluster.on('node-', () => {
|
||||
// if (++3) {
|
||||
// cluster.refreshSlotsCache(err => {
|
||||
// console.log('done', err);
|
||||
// });
|
||||
// i = 0;
|
||||
// }
|
||||
// })
|
||||
|
||||
// }, 5000);
|
||||
|
||||
// import { createCluster } from './packages/client/dist/index.js';
|
||||
// import { setTimeout } from 'node:timers/promises';
|
||||
|
||||
// const cluster = createCluster({
|
||||
// rootNodes: [{}]
|
||||
// });
|
||||
|
||||
// cluster.on('error', err => console.error(err));
|
||||
|
||||
// await cluster.connect();
|
||||
|
||||
// console.log(
|
||||
// await Promise.all([
|
||||
// cluster.ping(),
|
||||
// cluster.ping(),
|
||||
// cluster.set('1', '1'),
|
||||
// cluster.get('1'),
|
||||
// cluster.get('2'),
|
||||
// cluster.multi().ping().ping().get('a').set('a', 'b').get('a').execTyped()
|
||||
// // cluster
|
||||
// ])
|
||||
// );
|
||||
|
||||
// import { createClient } from './packages/client/dist/index.js';
|
||||
|
||||
// const client = createClient();
|
||||
|
||||
// client.a();
|
||||
|
||||
// client.on('error', err => console.error('Redis Client Error', err));
|
||||
|
||||
// await client.connect();
|
||||
|
||||
// const legacy = client.legacy();
|
||||
|
||||
// console.log(
|
||||
// await client.multi()
|
||||
// .ping()
|
||||
// .ping()
|
||||
// .aaa()
|
||||
// .exec(),
|
||||
// await client.multi()
|
||||
// .ping()
|
||||
// .ping()
|
||||
// .execTyped()
|
||||
// );
|
||||
|
||||
// legacy.multi()
|
||||
// .ping()
|
||||
// .ping()
|
||||
// .sendCommand(['PING', 'LEIBALE'])
|
||||
// .exec((err, replies) => {
|
||||
// console.log(err, replies);
|
||||
// client.destroy();
|
||||
// })
|
||||
|
||||
// for (let i = 0; i < 100; i++) {
|
||||
// const promises = [];
|
||||
// for (let j = 0; j < 5; j++) {
|
||||
// promises.push(client.sendCommand(['PING']));
|
||||
// }
|
||||
|
||||
// console.log(
|
||||
// await Promise.all(promises)
|
||||
// );
|
||||
// }
|
||||
|
||||
// // // const I = 100,
|
||||
// // // J = 1_000;
|
||||
|
||||
// // // for (let i = 0; i < I; i++) {
|
||||
// // // const promises = new Array(J);
|
||||
// // // for (let j = 0; j < J; j++) {
|
||||
// // // promises[j] = client.ping();
|
||||
// // // }
|
||||
|
||||
// // // await Promise.all(promises);
|
||||
// // // }
|
||||
|
||||
// import { writeFile } from 'node:fs/promises';
|
||||
|
||||
// function gen() {
|
||||
|
||||
// const lines = [
|
||||
// `// ${new Date().toJSON()}`,
|
||||
// 'import * as B from "./b";',
|
||||
// 'export default {'
|
||||
// ];
|
||||
|
||||
// for (let i = 0; i < 40000; i++) {
|
||||
// lines.push(` ${i}: B,`);
|
||||
// }
|
||||
|
||||
// lines.push('} as const;');
|
||||
|
||||
// return lines.join('\n');
|
||||
// }
|
||||
|
||||
// await writeFile('./a.ts', gen());
|
||||
|
||||
// import { createClient } from '@redis/client';
|
||||
|
||||
// console.log(new Date().toJSON());
|
||||
|
||||
// const client = createClient({
|
||||
// url: 'redis://default:VugDBHGYAectnTj25wmCCAuhPOu3xkhk@redis-11344.c240.us-east-1-3.ec2.cloud.redislabs.com:11344'
|
||||
// });
|
||||
|
||||
// client.on('error', err => console.error('11111', err, new Date().toJSON()));
|
||||
|
||||
// await client.connect();
|
||||
|
||||
// const client2 = createClient({
|
||||
// url: 'redis://default:VugDBHGYAectnTj25wmCCAuhPOu3xkhk@redis-11344.c240.us-east-1-3.ec2.cloud.redislabs.com:11344',
|
||||
// pingInterval: 60000
|
||||
// });
|
||||
|
||||
// client2.on('error', err => console.error('22222', err, new Date().toJSON()));
|
||||
|
||||
// await client2.connect();
|
||||
|
||||
import { createClient, RESP_TYPES } from '@redis/client';
|
||||
|
||||
const client = createClient({
|
||||
RESP: 3,
|
||||
name: 'test',
|
||||
commandOptions: {
|
||||
asap: true,
|
||||
typeMapping: {
|
||||
[RESP_TYPES.BLOB_STRING]: Buffer
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.on('error', err => console.error(err));
|
||||
|
||||
await client.connect();
|
||||
|
||||
|
||||
const controller = new AbortController();
|
||||
|
||||
try {
|
||||
const promise = client.withAbortSignal(controller.signal).set('key', 'value');
|
||||
controller.abort();
|
||||
console.log('!!', await promise);
|
||||
} catch (err) {
|
||||
// AbortError
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
client.ping('a'),
|
||||
client.ping('b')
|
||||
])
|
||||
|
||||
const asap = client.asap();
|
||||
|
||||
await Promise.all([
|
||||
asap.ping('aa'),
|
||||
asap.ping('bb')
|
||||
])
|
||||
|
||||
await client.set('another', 'value');
|
||||
|
||||
for await (const keys of client.scanIterator()) {
|
||||
console.log(keys);
|
||||
}
|
||||
|
||||
// console.log(
|
||||
// await Promise.all([
|
||||
// client.get('key'),
|
||||
// client.asap().get('a'),
|
||||
// client.withTypeMapping({}).get('key')
|
||||
// ])
|
||||
// );
|
||||
|
||||
// await client.set('key', 'value');
|
||||
|
||||
// const controller = new AbortController();
|
||||
|
||||
// controller.abort();
|
||||
|
||||
// client.withAbortSignal(controller.signal).get('key')
|
||||
// .then(a => console.log(a))
|
||||
// .catch(err => {
|
||||
// console.error(err);
|
||||
// });
|
||||
|
||||
// controller.abort();
|
||||
|
||||
// client.destroy();
|
232
test/package-lock.json
generated
Normal file
232
test/package-lock.json
generated
Normal file
@@ -0,0 +1,232 @@
|
||||
{
|
||||
"name": "test",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "test",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@redis/client": "^1.5.7",
|
||||
"ioredis": "^5.3.2",
|
||||
"local": "file:../packages/client",
|
||||
"redis": "^4.6.6",
|
||||
"redis-om": "^0.3.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@ioredis/commands": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
|
||||
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
|
||||
},
|
||||
"node_modules/@redis/bloom": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
|
||||
"integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/client": {
|
||||
"version": "1.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.7.tgz",
|
||||
"integrity": "sha512-gaOBOuJPjK5fGtxSseaKgSvjiZXQCdLlGg9WYQst+/GRUjmXaiB5kVkeQMRtPc7Q2t93XZcJfBMSwzs/XS9UZw==",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.2",
|
||||
"generic-pool": "3.9.0",
|
||||
"yallist": "4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/graph": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz",
|
||||
"integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/json": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz",
|
||||
"integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/search": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.2.tgz",
|
||||
"integrity": "sha512-/cMfstG/fOh/SsE+4/BQGeuH/JJloeWuH+qJzM8dbxuWvdWibWAOAHHCZTMPhV3xIlH4/cUEIA8OV5QnYpaVoA==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/time-series": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz",
|
||||
"integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cluster-key-slot": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/denque": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
|
||||
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/generic-pool": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
|
||||
"integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/ioredis": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz",
|
||||
"integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==",
|
||||
"dependencies": {
|
||||
"@ioredis/commands": "^1.1.1",
|
||||
"cluster-key-slot": "^1.1.0",
|
||||
"debug": "^4.3.4",
|
||||
"denque": "^2.1.0",
|
||||
"lodash.defaults": "^4.2.0",
|
||||
"lodash.isarguments": "^3.1.0",
|
||||
"redis-errors": "^1.2.0",
|
||||
"redis-parser": "^3.0.0",
|
||||
"standard-as-callback": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/ioredis"
|
||||
}
|
||||
},
|
||||
"node_modules/local": {
|
||||
"name": "@redis/client",
|
||||
"version": "2.0.0-next.1",
|
||||
"resolved": "file:../packages/client",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.2",
|
||||
"generic-pool": "3.9.0",
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.defaults": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
|
||||
},
|
||||
"node_modules/lodash.isarguments": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
|
||||
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/redis": {
|
||||
"version": "4.6.6",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-4.6.6.tgz",
|
||||
"integrity": "sha512-aLs2fuBFV/VJ28oLBqYykfnhGGkFxvx0HdCEBYdJ99FFbSEMZ7c1nVKwR6ZRv+7bb7JnC0mmCzaqu8frgOYhpA==",
|
||||
"dependencies": {
|
||||
"@redis/bloom": "1.2.0",
|
||||
"@redis/client": "1.5.7",
|
||||
"@redis/graph": "1.1.0",
|
||||
"@redis/json": "1.0.4",
|
||||
"@redis/search": "1.1.2",
|
||||
"@redis/time-series": "1.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-errors": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
|
||||
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-om": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/redis-om/-/redis-om-0.3.6.tgz",
|
||||
"integrity": "sha512-WRmrAm1n1EQIQbEwbfqpceuxHgr7LKOZ471c/KGxyOTVFFm53E0S7vFSZA7a1Jnga7aHTOYqLhhMWE0lKKdsNw==",
|
||||
"dependencies": {
|
||||
"redis": "^4.0.4",
|
||||
"ulid": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/redis-parser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
|
||||
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
|
||||
"dependencies": {
|
||||
"redis-errors": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/standard-as-callback": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
|
||||
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
|
||||
},
|
||||
"node_modules/ulid": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz",
|
||||
"integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==",
|
||||
"bin": {
|
||||
"ulid": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
19
test/package.json
Normal file
19
test/package.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "test",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@redis/client": "^1.5.7",
|
||||
"ioredis": "^5.3.2",
|
||||
"local": "file:../packages/client",
|
||||
"redis": "^4.6.6",
|
||||
"redis-om": "^0.3.6"
|
||||
}
|
||||
}
|
26
test/test.js
Normal file
26
test/test.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { createClient } from '@redis/client';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
|
||||
const client = createClient();
|
||||
client.on('error', err => console.error(err));
|
||||
|
||||
await client.connect();
|
||||
|
||||
await client.set('key', 'a'.repeat(1_000));
|
||||
|
||||
throw 'a';
|
||||
|
||||
while (true) {
|
||||
const promises = [];
|
||||
for (let i = 0; i < 20_000; i++) {
|
||||
promises.push(client.sendCommand(['HMSET', `aa${i.toString()}`, 'txt1', Math.random().toString()]));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
console.log(
|
||||
await client.dbSize(),
|
||||
(await client.info('MEMORY')).split('\n')[1]
|
||||
);
|
||||
|
||||
await setTimeout(1000);
|
||||
}
|
Reference in New Issue
Block a user