1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-07 13:22:56 +03:00
This commit is contained in:
Leibale
2023-04-30 10:46:43 -04:00
parent 88333c01de
commit e04609cc3a
5 changed files with 77 additions and 414 deletions

View File

@@ -1,4 +1,5 @@
export { RedisModules, RedisFunctions, RedisScripts, RespVersions } from './lib/RESP/types'; export { RedisModules, RedisFunctions, RedisScripts, RespVersions } from './lib/RESP/types';
export { RESP_TYPES } from './lib/RESP/decoder';
export { VerbatimString } from './lib/RESP/verbatim-string'; export { VerbatimString } from './lib/RESP/verbatim-string';
export { defineScript } from './lib/lua-script'; export { defineScript } from './lib/lua-script';
// export * from './lib/errors'; // export * from './lib/errors';

View File

@@ -4,7 +4,7 @@ import { SimpleError, BlobError, ErrorReply } from '../errors';
import { Flags } from './types'; import { Flags } from './types';
// https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md // https://github.com/redis/redis-specifications/blob/master/protocol/RESP3.md
export const TYPES = { export const RESP_TYPES = {
NULL: 95, // _ NULL: 95, // _
BOOLEAN: 35, // # BOOLEAN: 35, // #
NUMBER: 58, // : NUMBER: 58, // :
@@ -35,7 +35,7 @@ const ASCII = {
} as const; } as const;
export const PUSH_FLAGS = { export const PUSH_FLAGS = {
[TYPES.BLOB_STRING]: Buffer [RESP_TYPES.BLOB_STRING]: Buffer
}; };
// this was written with performance in mind, so it's not very readable... sorry :( // this was written with performance in mind, so it's not very readable... sorry :(
@@ -98,98 +98,98 @@ export class Decoder {
private _decodeTypeValue(type, chunk) { private _decodeTypeValue(type, chunk) {
switch (type) { switch (type) {
case TYPES.NULL: case RESP_TYPES.NULL:
this._config.onReply(this._decodeNull()); this._config.onReply(this._decodeNull());
return false; return false;
case TYPES.BOOLEAN: case RESP_TYPES.BOOLEAN:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeBoolean(chunk) this._decodeBoolean(chunk)
); );
case TYPES.NUMBER: case RESP_TYPES.NUMBER:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeNumber(chunk) this._decodeNumber(chunk)
); );
case TYPES.BIG_NUMBER: case RESP_TYPES.BIG_NUMBER:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeBigNumber( this._decodeBigNumber(
this._config.getFlags()[TYPES.BIG_NUMBER], this._config.getFlags()[RESP_TYPES.BIG_NUMBER],
chunk chunk
) )
); );
case TYPES.DOUBLE: case RESP_TYPES.DOUBLE:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeDouble( this._decodeDouble(
this._config.getFlags()[TYPES.DOUBLE], this._config.getFlags()[RESP_TYPES.DOUBLE],
chunk chunk
) )
); );
case TYPES.SIMPLE_STRING: case RESP_TYPES.SIMPLE_STRING:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeSimpleString( this._decodeSimpleString(
this._config.getFlags()[TYPES.SIMPLE_STRING], this._config.getFlags()[RESP_TYPES.SIMPLE_STRING],
chunk chunk
) )
); );
case TYPES.BLOB_STRING: case RESP_TYPES.BLOB_STRING:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeBlobString( this._decodeBlobString(
this._config.getFlags()[TYPES.BLOB_STRING], this._config.getFlags()[RESP_TYPES.BLOB_STRING],
chunk chunk
) )
); );
case TYPES.VERBATIM_STRING: case RESP_TYPES.VERBATIM_STRING:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeVerbatimString( this._decodeVerbatimString(
this._config.getFlags()[TYPES.VERBATIM_STRING], this._config.getFlags()[RESP_TYPES.VERBATIM_STRING],
chunk chunk
) )
); );
case TYPES.SIMPLE_ERROR: case RESP_TYPES.SIMPLE_ERROR:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onErrorReply, this._config.onErrorReply,
this._decodeSimpleError(chunk) this._decodeSimpleError(chunk)
); );
case TYPES.BLOB_ERROR: case RESP_TYPES.BLOB_ERROR:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onErrorReply, this._config.onErrorReply,
this._decodeBlobError(chunk) this._decodeBlobError(chunk)
); );
case TYPES.ARRAY: case RESP_TYPES.ARRAY:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeArray(this._config.getFlags(), chunk) this._decodeArray(this._config.getFlags(), chunk)
); );
case TYPES.SET: case RESP_TYPES.SET:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeSet(this._config.getFlags(), chunk) this._decodeSet(this._config.getFlags(), chunk)
); );
case TYPES.MAP: case RESP_TYPES.MAP:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onReply, this._config.onReply,
this._decodeMap(this._config.getFlags(), chunk) this._decodeMap(this._config.getFlags(), chunk)
); );
case TYPES.PUSH: case RESP_TYPES.PUSH:
return this._handleDecodedValue( return this._handleDecodedValue(
this._config.onPush, this._config.onPush,
this._decodeArray(PUSH_FLAGS, chunk) this._decodeArray(PUSH_FLAGS, chunk)
@@ -664,43 +664,43 @@ export class Decoder {
private _decodeNestedTypeValue(type, flags, chunk) { private _decodeNestedTypeValue(type, flags, chunk) {
switch (type) { switch (type) {
case TYPES.NULL: case RESP_TYPES.NULL:
return this._decodeNull(); return this._decodeNull();
case TYPES.BOOLEAN: case RESP_TYPES.BOOLEAN:
return this._decodeBoolean(chunk); return this._decodeBoolean(chunk);
case TYPES.NUMBER: case RESP_TYPES.NUMBER:
return this._decodeNumber(chunk); return this._decodeNumber(chunk);
case TYPES.BIG_NUMBER: case RESP_TYPES.BIG_NUMBER:
return this._decodeBigNumber(flags[TYPES.BIG_NUMBER], chunk); return this._decodeBigNumber(flags[RESP_TYPES.BIG_NUMBER], chunk);
case TYPES.DOUBLE: case RESP_TYPES.DOUBLE:
return this._decodeDouble(flags[TYPES.DOUBLE], chunk); return this._decodeDouble(flags[RESP_TYPES.DOUBLE], chunk);
case TYPES.SIMPLE_STRING: case RESP_TYPES.SIMPLE_STRING:
return this._decodeSimpleString(flags[TYPES.SIMPLE_STRING], chunk); return this._decodeSimpleString(flags[RESP_TYPES.SIMPLE_STRING], chunk);
case TYPES.BLOB_STRING: case RESP_TYPES.BLOB_STRING:
return this._decodeBlobString(flags[TYPES.BLOB_STRING], chunk); return this._decodeBlobString(flags[RESP_TYPES.BLOB_STRING], chunk);
case TYPES.VERBATIM_STRING: case RESP_TYPES.VERBATIM_STRING:
return this._decodeVerbatimString(flags[TYPES.VERBATIM_STRING], chunk); return this._decodeVerbatimString(flags[RESP_TYPES.VERBATIM_STRING], chunk);
case TYPES.SIMPLE_ERROR: case RESP_TYPES.SIMPLE_ERROR:
return this._decodeSimpleError(chunk); return this._decodeSimpleError(chunk);
case TYPES.BLOB_ERROR: case RESP_TYPES.BLOB_ERROR:
return this._decodeBlobError(chunk); return this._decodeBlobError(chunk);
case TYPES.ARRAY: case RESP_TYPES.ARRAY:
return this._decodeArray(flags, chunk); return this._decodeArray(flags, chunk);
case TYPES.SET: case RESP_TYPES.SET:
return this._decodeSet(flags, chunk); return this._decodeSet(flags, chunk);
case TYPES.MAP: case RESP_TYPES.MAP:
return this._decodeMap(flags, chunk); return this._decodeMap(flags, chunk);
} }
} }
@@ -805,7 +805,7 @@ export class Decoder {
} }
private _decodeSetItems(length, flags, chunk) { private _decodeSetItems(length, flags, chunk) {
return flags[TYPES.SET] === Set ? return flags[RESP_TYPES.SET] === Set ?
this._decodeSetAsSet( this._decodeSetAsSet(
new Set(), new Set(),
length, length,
@@ -888,7 +888,7 @@ export class Decoder {
} }
private _decodeMapItems(length, flags, chunk) { private _decodeMapItems(length, flags, chunk) {
switch (flags[TYPES.MAP]) { switch (flags[RESP_TYPES.MAP]) {
case Map: case Map:
return this._decodeMapAsMap( return this._decodeMapAsMap(
new Map(), new Map(),
@@ -978,11 +978,11 @@ export class Decoder {
private _decodeMapKeyValue(type, flags, chunk) { private _decodeMapKeyValue(type, flags, chunk) {
switch (type) { switch (type) {
// decode simple string map key as string (and not as buffer) // decode simple string map key as string (and not as buffer)
case TYPES.SIMPLE_STRING: case RESP_TYPES.SIMPLE_STRING:
return this._decodeSimpleString(String, chunk); return this._decodeSimpleString(String, chunk);
// decode blob string map key as string (and not as buffer) // decode blob string map key as string (and not as buffer)
case TYPES.BLOB_STRING: case RESP_TYPES.BLOB_STRING:
return this._decodeBlobString(String, chunk); return this._decodeBlobString(String, chunk);
default: default:

View File

@@ -1,13 +1,13 @@
import { RedisScriptConfig, SHA1 } from '../lua-script'; import { RedisScriptConfig, SHA1 } from '../lua-script';
import { TYPES } from './decoder'; import { RESP_TYPES } from './decoder';
import { VerbatimString } from './verbatim-string'; import { VerbatimString } from './verbatim-string';
export type RespTypes = typeof TYPES; export type RESP_TYPES = typeof RESP_TYPES;
export type RespTypesUnion = RespTypes[keyof RespTypes]; export type RespTypes = RESP_TYPES[keyof RESP_TYPES];
type RespType< type RespType<
RESP_TYPE extends RespTypesUnion, RESP_TYPE extends RespTypes,
DEFAULT, DEFAULT,
TYPES = never, TYPES = never,
FLAG_TYPES = DEFAULT | TYPES FLAG_TYPES = DEFAULT | TYPES
@@ -19,19 +19,19 @@ type RespType<
}; };
export type NullReply = RespType< export type NullReply = RespType<
RespTypes['NULL'], RESP_TYPES['NULL'],
null null
>; >;
export type BooleanReply< export type BooleanReply<
T extends boolean = boolean T extends boolean = boolean
> = RespType< > = RespType<
RespTypes['BOOLEAN'], RESP_TYPES['BOOLEAN'],
T T
>; >;
export type NumberReply< export type NumberReply<
T extends number = number T extends number = number
> = RespType< > = RespType<
RespTypes['NUMBER'], RESP_TYPES['NUMBER'],
T, T,
`${T}`, `${T}`,
number | string number | string
@@ -39,7 +39,7 @@ export type NumberReply<
export type BigNumberReply< export type BigNumberReply<
T extends bigint = bigint T extends bigint = bigint
> = RespType< > = RespType<
RespTypes['BIG_NUMBER'], RESP_TYPES['BIG_NUMBER'],
T, T,
number | `${T}`, number | `${T}`,
bigint | number | string bigint | number | string
@@ -47,7 +47,7 @@ export type BigNumberReply<
export type DoubleReply< export type DoubleReply<
T extends number = number T extends number = number
> = RespType< > = RespType<
RespTypes['DOUBLE'], RESP_TYPES['DOUBLE'],
T, T,
`${T}`, `${T}`,
number | string number | string
@@ -55,7 +55,7 @@ export type DoubleReply<
export type SimpleStringReply< export type SimpleStringReply<
T extends string = string T extends string = string
> = RespType< > = RespType<
RespTypes['SIMPLE_STRING'], RESP_TYPES['SIMPLE_STRING'],
T, T,
Buffer, Buffer,
string | Buffer string | Buffer
@@ -63,7 +63,7 @@ export type SimpleStringReply<
export type BlobStringReply< export type BlobStringReply<
T extends string = string T extends string = string
> = RespType< > = RespType<
RespTypes['BLOB_STRING'], RESP_TYPES['BLOB_STRING'],
T, T,
Buffer, Buffer,
string | Buffer string | Buffer
@@ -71,39 +71,39 @@ export type BlobStringReply<
export type VerbatimStringReply< export type VerbatimStringReply<
T extends string = string T extends string = string
> = RespType< > = RespType<
RespTypes['VERBATIM_STRING'], RESP_TYPES['VERBATIM_STRING'],
T, T,
Buffer | VerbatimString, Buffer | VerbatimString,
string | Buffer | VerbatimString string | Buffer | VerbatimString
>; >;
export type SimpleErrorReply = RespType< export type SimpleErrorReply = RespType<
RespTypes['SIMPLE_ERROR'], RESP_TYPES['SIMPLE_ERROR'],
Buffer Buffer
>; >;
export type BlobErrorReply = RespType< export type BlobErrorReply = RespType<
RespTypes['BLOB_ERROR'], RESP_TYPES['BLOB_ERROR'],
Buffer Buffer
>; >;
export type ArrayReply<T> = RespType< export type ArrayReply<T> = RespType<
RespTypes['ARRAY'], RESP_TYPES['ARRAY'],
Array<T>, Array<T>,
never, never,
Array<any> Array<any>
>; >;
export type TuplesReply<T extends [...Array<unknown>]> = RespType< export type TuplesReply<T extends [...Array<unknown>]> = RespType<
RespTypes['ARRAY'], RESP_TYPES['ARRAY'],
T, T,
never, never,
Array<any> Array<any>
>; >;
export type SetReply<T> = RespType< export type SetReply<T> = RespType<
RespTypes['SET'], RESP_TYPES['SET'],
Array<T>, Array<T>,
Set<T>, Set<T>,
Array<any> | Set<any> Array<any> | Set<any>
>; >;
export type MapReply<K, V> = RespType< export type MapReply<K, V> = RespType<
RespTypes['MAP'], RESP_TYPES['MAP'],
{ [key: string]: V }, { [key: string]: V },
Map<K, V> | Array<K | V>, Map<K, V> | Array<K | V>,
Map<any, any> | Array<any> Map<any, any> | Array<any>
@@ -114,7 +114,7 @@ type MapKeyValue = [key: BlobStringReply, value: unknown];
type MapTuples = Array<MapKeyValue>; type MapTuples = Array<MapKeyValue>;
export type TuplesToMapReply<T extends MapTuples> = RespType< export type TuplesToMapReply<T extends MapTuples> = RespType<
RespTypes['MAP'], RESP_TYPES['MAP'],
{ {
[P in T[number] as P[0] extends BlobStringReply<infer S> ? S : never]: P[1]; [P in T[number] as P[0] extends BlobStringReply<infer S> ? S : never]: P[1];
}, },
@@ -134,16 +134,16 @@ type FlattenTuples<T> = (
export type ReplyUnion = NullReply | BooleanReply | NumberReply | BigNumberReply | DoubleReply | SimpleStringReply | BlobStringReply | VerbatimStringReply | SimpleErrorReply | BlobErrorReply | export type ReplyUnion = NullReply | BooleanReply | NumberReply | BigNumberReply | DoubleReply | SimpleStringReply | BlobStringReply | VerbatimStringReply | SimpleErrorReply | BlobErrorReply |
// cannot reuse ArrayReply, SetReply and MapReply because of circular reference // cannot reuse ArrayReply, SetReply and MapReply because of circular reference
RespType< RespType<
RespTypes['ARRAY'], RESP_TYPES['ARRAY'],
Array<ReplyUnion> Array<ReplyUnion>
> | > |
RespType< RespType<
RespTypes['SET'], RESP_TYPES['SET'],
Array<ReplyUnion>, Array<ReplyUnion>,
Set<ReplyUnion> Set<ReplyUnion>
> | > |
RespType< RespType<
RespTypes['MAP'], RESP_TYPES['MAP'],
{ [key: string]: ReplyUnion }, { [key: string]: ReplyUnion },
Map<ReplyUnion, ReplyUnion> | Array<ReplyUnion | ReplyUnion> Map<ReplyUnion, ReplyUnion> | Array<ReplyUnion | ReplyUnion>
>; >;
@@ -152,10 +152,10 @@ export type Reply = ReplyWithFlags<ReplyUnion, {}>;
export type Flag<T> = ((...args: any) => T) | (new (...args: any) => T); export type Flag<T> = ((...args: any) => T) | (new (...args: any) => T);
type RespTypeUnion<T> = T extends RespType<RespTypesUnion, unknown, unknown, infer FLAG_TYPES> ? FLAG_TYPES : never; type RespTypeUnion<T> = T extends RespType<RespTypes, unknown, unknown, infer FLAG_TYPES> ? FLAG_TYPES : never;
export type Flags = { export type Flags = {
[P in RespTypesUnion]?: Flag<RespTypeUnion<Extract<ReplyUnion, RespType<P, any, any, any>>>>; [P in RespTypes]?: Flag<RespTypeUnion<Extract<ReplyUnion, RespType<P, any, any, any>>>>;
}; };
type MapKey< type MapKey<
@@ -163,8 +163,8 @@ type MapKey<
FLAGS extends Flags FLAGS extends Flags
> = ReplyWithFlags<T, FLAGS & { > = ReplyWithFlags<T, FLAGS & {
// simple and blob strings as map keys decoded as strings // simple and blob strings as map keys decoded as strings
[TYPES.SIMPLE_STRING]: StringConstructor; [RESP_TYPES.SIMPLE_STRING]: StringConstructor;
[TYPES.BLOB_STRING]: StringConstructor; [RESP_TYPES.BLOB_STRING]: StringConstructor;
}>; }>;
export type ReplyWithFlags< export type ReplyWithFlags<
@@ -299,13 +299,13 @@ type Resp2Array<T> = (
export type Resp2Reply<RESP3REPLY> = ( export type Resp2Reply<RESP3REPLY> = (
RESP3REPLY extends RespType<infer RESP_TYPE, infer DEFAULT, infer TYPES, unknown> ? RESP3REPLY extends RespType<infer RESP_TYPE, infer DEFAULT, infer TYPES, unknown> ?
// TODO: RESP3 only scalar types // TODO: RESP3 only scalar types
RESP_TYPE extends RespTypes['DOUBLE'] ? BlobStringReply : RESP_TYPE extends RESP_TYPES['DOUBLE'] ? BlobStringReply :
RESP_TYPE extends RespTypes['ARRAY'] | RespTypes['SET'] ? RespType< RESP_TYPE extends RESP_TYPES['ARRAY'] | RESP_TYPES['SET'] ? RespType<
RESP_TYPE, RESP_TYPE,
Resp2Array<DEFAULT> Resp2Array<DEFAULT>
> : > :
RESP_TYPE extends RespTypes['MAP'] ? RespType< RESP_TYPE extends RESP_TYPES['MAP'] ? RespType<
RespTypes['ARRAY'], RESP_TYPES['ARRAY'],
Resp2Array<Extract<TYPES, Array<any>>> Resp2Array<Extract<TYPES, Array<any>>>
> : > :
RespType< RespType<

View File

@@ -1,6 +1,6 @@
import * as LinkedList from 'yallist'; import * as LinkedList from 'yallist';
import encodeCommand from '../RESP/encoder'; import encodeCommand from '../RESP/encoder';
import { Decoder, PUSH_FLAGS, TYPES } from '../RESP/decoder'; import { Decoder, PUSH_FLAGS, RESP_TYPES } from '../RESP/decoder';
import { CommandArguments, Flags, ReplyUnion, RespVersions } from '../RESP/types'; import { CommandArguments, Flags, 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';
@@ -32,7 +32,7 @@ const PONG = Buffer.from('pong');
const RESP2_PUSH_FLAGS = { const RESP2_PUSH_FLAGS = {
...PUSH_FLAGS, ...PUSH_FLAGS,
[TYPES.SIMPLE_STRING]: Buffer [RESP_TYPES.SIMPLE_STRING]: Buffer
}; };
export default class RedisCommandsQueue { export default class RedisCommandsQueue {
@@ -125,7 +125,7 @@ export default class RedisCommandsQueue {
if (PONG.equals(reply[0] as Buffer)) { if (PONG.equals(reply[0] as Buffer)) {
const { resolve, flags } = this._waitingForReply.shift()!, const { resolve, flags } = this._waitingForReply.shift()!,
buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer; buffer = ((reply[1] as Buffer).length === 0 ? reply[0] : reply[1]) as Buffer;
resolve(flags?.[TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString()); resolve(flags?.[RESP_TYPES.SIMPLE_STRING] === Buffer ? buffer : buffer.toString());
return; return;
} }
} }

View File

@@ -1,338 +0,0 @@
import { setTimeout } from 'timers/promises';
import { createClient, defineScript, createCluster } from './dist/index.js';
import { TYPES } from './dist/lib/RESP/decoder.js';
async function client() {
console.log(`!!! CLIENT !!!`);
const client = createClient({
RESP,
isolationPoolOptions: {
max: 5
},
modules: {
/**
* module jsdoc
*/
module: {
/**
* module ping jsdoc
*/
ping: {
/**
* @param {string} [message]
*/
transformArguments(message) {
const args = ['PING'];
if (message) {
args.push(message);
}
return args;
},
/**
* @callback PingReply
* @returns {import('./lib/RESP/types').SimpleStringReply}
*
* @type {PingReply}
*/
transformReply: undefined
},
/**
* module square jsdoc
*/
square: {
/**
* @param {number} number
*/
transformArguments(number) {
return ['FCALL_RO', 'square', '0', number.toString()];
},
/**
* @callback SquareResp2
* @returns {import('./lib/RESP/types').BlobStringReply}
*
* @callback SquareResp3
* @returns {import('./lib/RESP/types').DoubleReply}
*
* @type {{ 2: SquareResp2, 3: SquareResp3 }}
*/
transformReply: undefined
}
}
},
functions: {
/**
* library jsdoc
*/
library: {
/**
* library square jsdoc
*/
square: {
IS_READ_ONLY: true,
NUMBER_OF_KEYS: 0,
/**
* @param {number} number
*/
transformArguments(number) {
return [number.toString()];
},
/**
* @callback SquareResp2
* @returns {import('./lib/RESP/types').BlobStringReply}
*
* @callback SquareResp3
* @returns {import('./lib/RESP/types').DoubleReply}
*
* @type {{ 2: SquareResp2, 3: SquareResp3 }}
*/
transformReply: undefined
}
}
},
scripts: {
/**
* square jsdoc
*/
square: defineScript({
SCRIPT: 'return { double = ARGV[1] * ARGV[1] };',
NUMBER_OF_KEYS: 0,
/**
* @param {number} number
*/
transformArguments(number) {
return [number.toString()];
},
/**
* @callback SquareResp2
* @returns {import('./lib/RESP/types').BlobStringReply}
*
* @callback SquareResp3
* @returns {import('./lib/RESP/types').DoubleReply}
*
* @type {{ 2: SquareResp2, 3: SquareResp3 }}
*/
transformReply: undefined
})
}
});
const multi = client.multi()
.get('a')
.set('a', 'b');
for (let i = 0; i< 10; i++) {
multi.incr('a');
}
const result = await multi.exec();
const bufferClient = client.withFlags({
[TYPES.SIMPLE_STRING]: Buffer,
[TYPES.BLOB_STRING]: Buffer
});
client.on('error', err => console.error(err));
await client.connect();
client.ping()
// console.log(
// 'SCAN',
// await client.scan(0),
// await bufferClient.scan(0)
// );
// const fn =
// `#!LUA name=math
// redis.register_function{
// function_name = "square",
// callback = function(keys, args) return { double = args[1] * args[1] } end,
// flags = { "no-writes" }
// }`;
// await client.sendCommand(['FLUSHALL']);
// await client.sendCommand(['FUNCTION', 'LOAD', 'REPLACE', fn]);
// console.log(
// 'info:\n',
// await client.info(),
// 'info with flags:\n',
// await client.withFlags({
// [TYPES.VERBATIM_STRING]: VerbatimString
// }).info(),
// );
// console.log(
// 'client.module.square (module):',
// await client.module.square(1),
// await client.withFlags({
// [TYPES.DOUBLE]: String
// }).module.square(1)
// );
// console.log(
// 'client.library.square (function):',
// await client.library.square(2),
// await client.withFlags({
// [TYPES.DOUBLE]: String
// }).library.square(2)
// );
// console.log(
// 'client.square (script):',
// await client.square(4),
// await client.withFlags({
// [TYPES.DOUBLE]: String
// }).square(4)
// );
// console.log(
// 'MULTI',
// await client.multi()
// .ping()
// .module.ping()
// .library.square(2)
// .square(4)
// .exec()
// );
// console.log(
// 'SET key value',
// await client.set('key', 'value'),
// );
// console.log(
// 'GET key',
// await client.get('key'),
// );
// console.log(
// 'GET key (bufferClient)',
// await bufferClient.get('key'),
// );
// console.log(
// 'sendCommand DEL key',
// await client.sendCommand(['DEL', 'key'])
// );
// console.log(
// 'HSET key field value',
// await client.hSet('key', 'field', 'value')
// );
// console.log(
// 'HGET key field',
// await client.hGet('key', 'field')
// );
// console.log(
// 'HGETALL key',
// await client.hGetAll('key')
// );
// console.log(
// 'HGETALL key (bufferClient)',
// await bufferClient.hGetAll('key')
// );
// console.log(
// 'CLIENT ID',
// await client.sendCommand(['CLIENT', 'ID']),
// );
// await client.subscribe('channel', message => {
// console.log('channel', message);
// });
// let publisherClient;
// if (RESP !== 3) {
// publisherClient = client.duplicate();
// publisherClient.on('error', err => console.error('PubSubClient error', err));
// await publisherClient.connect();
// }
// const TIMES = 3;
// console.log(
// `[PUBLISH channel <i>] [PING <i>] * ${TIMES}`,
// await Promise.all(
// Array.from({ length: 5 }).map((_, i) =>
// Promise.all([
// (publisherClient ?? client).sendCommand(['PUBLISH', 'channel', i.toString()]).catch(),
// client.ping(i.toString()),
// client.isolated().clientId(),
// client.executeIsolated(client => client.clientId())
// ])
// )
// )
// );
const entries = Array.from({ length: 100 }).map((_, i) => ['{a}' + i.toString(), i.toString()])
await client.mSet(entries);
for await (const key of client.scanIterator()) {
console.log('SCAN', key);
}
await client.hSet('hash', entries.flat());
for await (const entry of client.hScanIterator('hash')) {
console.log('HSCAN', entry)
}
await Promise.all([
// publisherClient?.disconnect(),
client.disconnect()
]);
}
async function cluster() {
console.log(`!!! CLUSTER !!!`);
const cluster = createCluster({
rootNodes: [{}],
RESP
});
cluster.on('error', err => console.error(err));
await cluster.connect();
console.log(
'SET key value',
await cluster.set('key', 'value')
);
console.log(
'GET key',
await cluster.get('key')
);
await cluster.subscribe('channel', message => {
console.log('(cluster) channel', message);
});
const CLUSTER_TIMES = 3;
console.log(
`[PUBLISH channel <i>] [PING <i>] * ${CLUSTER_TIMES}`,
await Promise.all(
Array.from({ length: 5 }).map(async (_, i) => {
const client = await cluster.nodeClient(cluster.getRandomNode());
return client.sendCommand(['PUBLISH', 'channel', i.toString()]);
})
)
);
// wait for messages
await setTimeout(1000);
await cluster.disconnect();
}
const RESP = 3;
await client();
// await cluster();