@valkey/valkey-glide
Version:
General Language Independent Driver for the Enterprise (GLIDE) for Valkey
1,109 lines (1,108 loc) • 61.1 kB
JavaScript
"use strict";
/**
* Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.GlideClusterClient = exports.GlideClusterClientConfiguration = exports.ALL_SHARDED_CHANNELS = void 0;
const native_1 = require("../build-ts/native");
const ProtobufMessage_1 = require("../build-ts/ProtobufMessage");
const BaseClient_1 = require("./BaseClient");
const Commands_1 = require("./Commands");
/**
* Constant representing all sharded channels.
* Use this to unsubscribe from all sharded channel subscriptions at once..
*
* @example
* ```typescript
* await client.sunsubscribeLazy(ALL_SHARDED_CHANNELS);
* ```
*/
exports.ALL_SHARDED_CHANNELS = null;
/* eslint-disable-next-line @typescript-eslint/no-namespace */
var GlideClusterClientConfiguration;
(function (GlideClusterClientConfiguration) {
/**
* Enum representing pubsub subscription modes.
* @see {@link https://valkey.io/docs/topics/pubsub/|Valkey PubSub Documentation} for more details.
*/
let PubSubChannelModes;
(function (PubSubChannelModes) {
/**
* Use exact channel names.
*/
PubSubChannelModes[PubSubChannelModes["Exact"] = 0] = "Exact";
/**
* Use channel name patterns.
*/
PubSubChannelModes[PubSubChannelModes["Pattern"] = 1] = "Pattern";
/**
* Use sharded pubsub. Available since Valkey version 7.0.
*/
PubSubChannelModes[PubSubChannelModes["Sharded"] = 2] = "Sharded";
})(PubSubChannelModes = GlideClusterClientConfiguration.PubSubChannelModes || (GlideClusterClientConfiguration.PubSubChannelModes = {}));
})(GlideClusterClientConfiguration || (exports.GlideClusterClientConfiguration = GlideClusterClientConfiguration = {}));
/**
* @internal
* Convert {@link ClusterGlideRecord} to {@link ClusterResponse}.
*
* @param res - Value received from Glide core.
* @param isRoutedToSingleNodeByDefault - Default routing policy.
* @param route - The route.
* @returns Converted value.
*/
function convertClusterGlideRecord(res, isRoutedToSingleNodeByDefault, route) {
const isSingleNodeResponse =
// route not given and command is routed by default to a random node
(!route && isRoutedToSingleNodeByDefault) ||
// or route is given and it is a single node route
(Boolean(route) && route !== "allPrimaries" && route !== "allNodes");
return isSingleNodeResponse
? res
: (0, BaseClient_1.convertGlideRecordToRecord)(res);
}
/**
* Client used for connection to cluster servers.
* Use {@link createClient} to request a client.
*
* @see For full documentation refer to {@link https://glide.valkey.io/how-to/client-initialization/#cluster | Valkey GLIDE Documentation}.
*/
class GlideClusterClient extends BaseClient_1.BaseClient {
/**
* @internal
*/
createClientRequest(options) {
const configuration = super.createClientRequest(options);
configuration.clusterModeEnabled = true;
// "enabledDefaultConfigs" is the default configuration and doesn't need setting
if (options.periodicChecks !== undefined &&
options.periodicChecks !== "enabledDefaultConfigs") {
if (options.periodicChecks === "disabled") {
configuration.periodicChecksDisabled =
ProtobufMessage_1.connection_request.PeriodicChecksDisabled.create();
}
else {
configuration.periodicChecksManualInterval =
ProtobufMessage_1.connection_request.PeriodicChecksManualInterval.create({
durationInSec: options.periodicChecks.duration_in_sec,
});
}
}
this.configurePubsub(options, configuration);
if (options.advancedConfiguration) {
this.configureAdvancedConfigurationBase(options.advancedConfiguration, configuration);
// Set refresh topology from initial nodes
if (options.advancedConfiguration
.refreshTopologyFromInitialNodes !== undefined) {
configuration.refreshTopologyFromInitialNodes =
options.advancedConfiguration.refreshTopologyFromInitialNodes;
}
}
return configuration;
}
/**
* Creates a new `GlideClusterClient` instance and establishes connections to a Valkey Cluster.
*
* @param options - The configuration options for the client, including cluster addresses, database selection, authentication credentials, TLS settings, periodic checks, and Pub/Sub subscriptions.
* @returns A promise that resolves to a connected `GlideClusterClient` instance.
*
* @remarks
* Use this static method to create and connect a `GlideClusterClient` to a Valkey Cluster.
* The client will automatically handle connection establishment, including cluster topology discovery, database selection, and handling of authentication and TLS configurations.
*
* @example
* ```typescript
* // Connecting to a Cluster
* import { GlideClusterClient, GlideClusterClientConfiguration } from '@valkey/valkey-glide';
*
* const client = await GlideClusterClient.createClient({
* addresses: [
* { host: 'address1.example.com', port: 6379 },
* { host: 'address2.example.com', port: 6379 },
* ],
* databaseId: 5, // Connect to database 5 (requires Valkey 9.0+)
* credentials: {
* username: 'user1',
* password: 'passwordA',
* },
* useTLS: true,
* periodicChecks: {
* duration_in_sec: 30, // Perform periodic checks every 30 seconds
* },
* pubsubSubscriptions: {
* channelsAndPatterns: {
* [GlideClusterClientConfiguration.PubSubChannelModes.Exact]: new Set(['updates']),
* [GlideClusterClientConfiguration.PubSubChannelModes.Sharded]: new Set(['sharded_channel']),
* },
* callback: (msg) => {
* console.log(`Received message: ${msg.payload}`);
* },
* },
* connectionBackoff: {
* numberOfRetries: 5,
* factor: 1000,
* exponentBase: 2,
* jitter: 20,
* },
* });
* ```
*
* @remarks
* - **Cluster Topology Discovery**: The client will automatically discover the cluster topology based on the seed addresses provided.
* - **Database Selection**: Use `databaseId` to specify which logical database to connect to. Requires Valkey 9.0+ with multi-database cluster mode enabled.
* - **Authentication**: If `credentials` are provided, the client will attempt to authenticate using the specified username and password.
* - **TLS**: If `useTLS` is set to `true`, the client will establish secure connections using TLS.
* Should match the TLS configuration of the server/cluster, otherwise the connection attempt will fail.
* For advanced tls configuration, please use the {@link AdvancedGlideClusterClientConfiguration} option.
* - **Periodic Checks**: The `periodicChecks` setting allows you to configure how often the client checks for cluster topology changes.
* - **Pub/Sub Subscriptions**: Any channels or patterns specified in `pubsubSubscriptions` will be subscribed to upon connection.
*/
static async createClient(options) {
return await super.createClientInternal(options, (socket, options) => new GlideClusterClient(socket, options));
}
/**
* @internal
*/
static async __createClient(options, connectedSocket) {
return super.__createClientInternal(options, connectedSocket, (socket, options) => new GlideClusterClient(socket, options));
}
/**
* @internal
*/
scanOptionsToProto(cursor, options) {
const command = ProtobufMessage_1.command_request.ClusterScan.create();
command.cursor = cursor;
if (options?.match) {
command.matchPattern =
typeof options.match === "string"
? Buffer.from(options.match)
: options.match;
}
if (options?.count) {
command.count = options.count;
}
if (options?.type) {
command.objectType = options.type;
}
command.allowNonCoveredSlots = options?.allowNonCoveredSlots ?? false;
return command;
}
/**
* @internal
*/
createClusterScanPromise(cursor, options) {
this.ensureClientIsOpen();
// separate decoder option from scan options
const { decoder = this.defaultDecoder, ...scanOptions } = options || {};
const cursorId = cursor.getCursor();
const command = this.scanOptionsToProto(cursorId, scanOptions);
return new Promise((resolve, reject) => {
const callbackIdx = this.getCallbackIndex();
this.promiseCallbackFunctions[callbackIdx] = [
(resolveAns) => {
try {
resolve([
new native_1.ClusterScanCursor(resolveAns[0].toString()),
resolveAns[1],
]);
}
catch (error) {
reject(error);
}
},
reject,
decoder,
];
this.writeOrBufferRequest(new ProtobufMessage_1.command_request.CommandRequest({
callbackIdx,
clusterScan: command,
}), (message, writer) => {
ProtobufMessage_1.command_request.CommandRequest.encodeDelimited(message, writer);
});
});
}
/**
* Incrementally iterates over the keys in the Cluster.
*
* This command is similar to the `SCAN` command but designed for Cluster environments.
* It uses a {@link ClusterScanCursor} object to manage iterations.
*
* For each iteration, use the new cursor object to continue the scan.
* Using the same cursor object for multiple iterations may result in unexpected behavior.
*
* For more information about the Cluster Scan implementation, see
* {@link https://glide.valkey.io/concepts/client-features/cluster-scan/ | Cluster Scan}.
*
* This method can iterate over all keys in the database from the start of the scan until it ends.
* The same key may be returned in multiple scan iterations.
* The API does not accept `route` as it go through all slots in the cluster.
*
* @see {@link https://valkey.io/commands/scan/ | valkey.io} for more details.
*
* @param cursor - The cursor object that wraps the scan state.
* To start a new scan, create a new empty `ClusterScanCursor` using {@link ClusterScanCursor}.
* @param options - (Optional) The scan options, see {@link ClusterScanOptions} and {@link DecoderOption}.
* @returns A Promise resolving to an array containing the next cursor and an array of keys,
* formatted as [`ClusterScanCursor`, `string[]`].
*
* @example
* ```typescript
* // Iterate over all keys in the cluster
* await client.mset([{key: "key1", value: "value1"}, {key: "key2", value: "value2"}, {key: "key3", value: "value3"}]);
* let cursor = new ClusterScanCursor();
* const allKeys: GlideString[] = [];
* let keys: GlideString[] = [];
* while (!cursor.isFinished()) {
* [cursor, keys] = await client.scan(cursor, { count: 10 });
* allKeys.push(...keys);
* }
* console.log(allKeys); // ["key1", "key2", "key3"]
*
* // Iterate over keys matching a pattern
* await client.mset([{key: "key1", value: "value1"}, {key: "key2", value: "value2"}, {key: "notMyKey", value: "value3"}, {key: "somethingElse", value: "value4"}]);
* let cursor = new ClusterScanCursor();
* const matchedKeys: GlideString[] = [];
* let keys: GlideString[] = [];
* while (!cursor.isFinished()) {
* [cursor, keys] = await client.scan(cursor, { match: "*key*", count: 10 });
* matchedKeys.push(...keys);
* }
* console.log(matchedKeys); // ["key1", "key2"]
*
* // Iterate over keys of a specific type
* await client.mset([{key: "key1", value: "value1"}, {key: "key2", value: "value2"}, {key: "key3", value: "value3"}]);
* await client.sadd("thisIsASet", ["value4"]);
* let cursor = new ClusterScanCursor();
* const stringKeys: GlideString[] = [];
* let keys: GlideString[];
* while (!cursor.isFinished()) {
* [cursor, keys] = await client.scan(cursor, { type: ObjectType.STRING });
* stringKeys.push(...keys);
* }
* console.log(stringKeys); // ["key1", "key2", "key3"]
* ```
*/
async scan(cursor, options) {
return this.createClusterScanPromise(cursor, options);
}
/** Executes a single command, without checking inputs. Every part of the command, including subcommands,
* should be added as a separate value in args.
* The command will be routed automatically based on the passed command's default request policy, unless `route` is provided,
* in which case the client will route the command to the nodes defined by `route`.
*
* Note: An error will occur if the string decoder is used with commands that return only bytes as a response.
*
* @see {@link https://glide.valkey.io/concepts/client-features/custom-commands/|Glide for Valkey Wiki} for details on the restrictions and limitations of the custom command API.
*
* @param args - A list including the command name and arguments for the custom command.
* @param options - (Optional) See {@link RouteOption} and {@link DecoderOption}
* @returns The executed custom command return value.
*
* @example
* ```typescript
* // Example usage of customCommand method to retrieve pub/sub clients with routing to all primary nodes
* const result = await client.customCommand(["CLIENT", "LIST", "TYPE", "PUBSUB"], {route: "allPrimaries", decoder: Decoder.String});
* console.log(result); // Output: Returns a list of all pub/sub clients
* ```
*/
async customCommand(args, options) {
const command = (0, Commands_1.createCustomCommand)(args);
return super.createWritePromise(command, options);
}
/**
* Executes a batch by processing the queued commands.
*
* **Routing Behavior:**
*
* - If a `route` is specified in {@link ClusterBatchOptions}, the entire batch is sent to the specified node.
* - If no `route` is specified:
* - **Atomic batches (Transactions):** Routed to the slot owner of the first key in the batch. If no key is found, the request is sent to a random node.
* - **Non-atomic batches (Pipelines):** Each command is routed to the node owning the corresponding key's slot. If no key is present, routing follows the command's request policy. Multi-node commands are automatically split and dispatched to the appropriate nodes.
*
* **Behavior Notes:**
*
* - **Atomic Batches (Transactions):** All key-based commands must map to the same hash slot. If keys span different slots, the transaction will fail. If the transaction fails due to a `WATCH` command, `exec` will return `null`.
*
* @see {@link https://github.com/valkey-io/valkey-glide/wiki/NodeJS-wrapper#transaction|Valkey GLIDE Documentation} for details on Valkey Transactions.
*
* **Retry and Redirection:**
*
* - If a redirection error occurs:
* - **Atomic batches (Transactions):** The entire transaction will be redirected.
* - **Non-atomic batches (Pipelines):** Only commands that encountered redirection errors will be retried.
* - Retries for failures will be handled according to the configured {@link BatchRetryStrategy}.
*
* @param batch - A {@link ClusterBatch} containing the commands to execute.
* @param raiseOnError - Determines how errors are handled within the batch response.
* - If `true`, the first encountered error in the batch will be raised as an exception of type {@link RequestError}
* after all retries and reconnections have been exhausted.
* - If `false`, errors will be included as part of the batch response, allowing the caller to process both successful and failed commands together.
* In this case, error details will be provided as instances of {@link RequestError} in the response list.
* @param options - (Optional) {@link ClusterBatchOptions} and {@link DecoderOption} specifying execution and decoding behavior.
* @returns A Promise resolving to an array of results, where each entry corresponds to a command’s execution result.
* - If the transaction fails due to a `WATCH` command, the promise resolves to `null`.
*
* @see {@link https://valkey.io/docs/topics/transactions/|Valkey Transactions (Atomic Batches)}
* @see {@link https://valkey.io/docs/topics/pipelining/|Valkey Pipelines (Non-Atomic Batches)}
* @example
* ```typescript
* // Atomic batch (transaction): all keys must share the same hash slot
* const atomicBatch = new ClusterBatch(true)
* .set('key', '1')
* .incr('key')
* .get('key');
*
* const atomicOptions = {timeout: 1000};
* const atomicResult = await clusterClient.exec(atomicBatch, false, atomicOptions);
* console.log('Atomic Batch Result:', atomicResult);
* // Output: ['OK', 2, '2']
*
* // Non-atomic batch (pipeline): keys may span different hash slots
* const nonAtomicBatch = new ClusterBatch(false)
* .set('key1', 'value1')
* .set('key2', 'value2')
* .get('key1')
* .get('key2');
*
* const pipelineOptions = { retryStrategy: { retryServerError: true, retryConnectionError: false } };
* const nonAtomicResult = await clusterClient.exec(nonAtomicBatch, false, pipelineOptions);
* console.log(nonAtomicResult);
* // Output: ['OK', 'OK', 'value1', 'value2']
* ```
*/
async exec(batch, raiseOnError, options) {
return this.createWritePromise(batch.commands, options, batch.isAtomic, raiseOnError).then((result) => this.processResultWithSetCommands(result, batch.setCommandsIndexes));
}
/**
* Pings the server.
*
* The command will be routed to all primary nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/ping/|valkey.io} for details.
*
* @param options - (Optional) Additional parameters:
* - (Optional) `message` : a message to include in the `PING` command.
* + If not provided, the server will respond with `"PONG"`.
* + If provided, the server will respond with a copy of the message.
* - (Optional) `route`: see {@link RouteOption}.
* - (Optional) `decoder`: see {@link DecoderOption}.
* @returns `"PONG"` if `message` is not provided, otherwise return a copy of `message`.
*
* @example
* ```typescript
* // Example usage of ping method without any message
* const result = await client.ping();
* console.log(result); // Output: 'PONG'
* ```
*
* @example
* ```typescript
* // Example usage of ping method with a message
* const result = await client.ping("Hello");
* console.log(result); // Output: 'Hello'
* ```
*/
async ping(options) {
return this.createWritePromise((0, Commands_1.createPing)(options?.message), options);
}
/**
* Gets information and statistics about the server.
*
* The command will be routed to all primary nodes, unless `route` is provided.
*
* Starting from server version 7, command supports multiple section arguments.
*
* @see {@link https://valkey.io/commands/info/|valkey.io} for details.
*
* @param options - (Optional) Additional parameters:
* - (Optional) `sections`: a list of {@link InfoOptions} values specifying which sections of information to retrieve.
* When no parameter is provided, {@link InfoOptions.Default|Default} is assumed.
* - (Optional) `route`: see {@link RouteOption}.
* @returns A string containing the information for the sections requested.
* When specifying a route other than a single node,
* it returns a dictionary where each address is the key and its corresponding node response is the value.
*
* @example
* ```typescript
* // Example usage of the info method with retrieving total_net_input_bytes from the result
* const result = await client.info(new Section[] { Section.STATS });
* console.log(someClusterParsingFunction(result, "total_net_input_bytes")); // Output: 1
* ```
*/
async info(options) {
return this.createWritePromise((0, Commands_1.createInfo)(options?.sections), { decoder: BaseClient_1.Decoder.String, ...options }).then((res) => convertClusterGlideRecord(res, false, options?.route));
}
/**
* Gets the name of the connection to which the request is routed.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/client-getname/|valkey.io} for details.
*
* @param options - (Optional) See {@link RouteOption} and {@link DecoderOption}.
*
* @returns - The name of the client connection as a string if a name is set, or `null` if no name is assigned.
* When specifying a route other than a single node, it returns a dictionary where each address is the key and
* its corresponding node response is the value.
*
* @example
* ```typescript
* // Example usage of client_getname method
* const result = await client.client_getname();
* console.log(result); // Output: 'Connection Name'
* ```
*
* @example
* ```typescript
* // Example usage of clientGetName method with routing to all nodes
* const result = await client.clientGetName('allNodes');
* console.log(result); // Output: {'addr': 'Connection Name', 'addr2': 'Connection Name', 'addr3': 'Connection Name'}
* ```
*/
async clientGetName(options) {
return this.createWritePromise((0, Commands_1.createClientGetName)(), options).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Rewrites the configuration file with the current configuration.
*
* The command will be routed to a all nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/config-rewrite/|valkey.io} for details.
*
* @param options - (Optional) See {@link RouteOption}.
* @returns `"OK"` when the configuration was rewritten properly. Otherwise, an error is thrown.
*
* @example
* ```typescript
* // Example usage of configRewrite command
* const result = await client.configRewrite();
* console.log(result); // Output: 'OK'
* ```
*/
async configRewrite(options) {
return this.createWritePromise((0, Commands_1.createConfigRewrite)(), {
decoder: BaseClient_1.Decoder.String,
...options,
});
}
/**
* Resets the statistics reported by the server using the `INFO` and `LATENCY HISTOGRAM` commands.
*
* The command will be routed to all nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/config-resetstat/|valkey.io} for details.
*
* @param options - (Optional) See {@link RouteOption}.
* @returns always `"OK"`.
*
* @example
* ```typescript
* // Example usage of configResetStat command
* const result = await client.configResetStat();
* console.log(result); // Output: 'OK'
* ```
*/
async configResetStat(options) {
return this.createWritePromise((0, Commands_1.createConfigResetStat)(), {
decoder: BaseClient_1.Decoder.String,
...options,
});
}
/**
* Returns the current connection ID.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/client-id/|valkey.io} for details.
*
* @param options - (Optional) See {@link RouteOption}.
* @returns The ID of the connection. When specifying a route other than a single node,
* it returns a dictionary where each address is the key and its corresponding node response is the value.
*
* @example
* ```typescript
* const result = await client.clientId();
* console.log("Connection id: " + result);
* ```
*/
async clientId(options) {
return this.createWritePromise((0, Commands_1.createClientId)(), options).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Reads the configuration parameters of the running server.
* Starting from server version 7, command supports multiple parameters.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/config-get/|valkey.io} for details.
*
* @param parameters - A list of configuration parameter names to retrieve values for.
* @param options - (Optional) See {@link RouteOption} and {@link DecoderOption}.
*
* @returns A map of values corresponding to the configuration parameters. When specifying a route other than a single node,
* it returns a dictionary where each address is the key and its corresponding node response is the value.
*
* @example
* ```typescript
* // Example usage of config_get method with a single configuration parameter with routing to a random node
* const result = await client.config_get(["timeout"], "randomNode");
* console.log(result); // Output: {'timeout': '1000'}
* ```
*
* @example
* ```typescript
* // Example usage of configGet method with multiple configuration parameters
* const result = await client.configGet(["timeout", "maxmemory"]);
* console.log(result); // Output: {'timeout': '1000', 'maxmemory': '1GB'}
* ```
*/
async configGet(parameters, options) {
return this.createWritePromise((0, Commands_1.createConfigGet)(parameters), options).then((res) => (0, BaseClient_1.convertGlideRecordToRecord)(res));
}
/**
* Sets configuration parameters to the specified values.
* Starting from server version 7, command supports multiple parameters.
*
* The command will be routed to all nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/config-set/|valkey.io} for details.
*
* @param parameters - A map consisting of configuration parameters and their respective values to set.
* @param options - (Optional) See {@link RouteOption}.
* @returns "OK" when the configuration was set properly. Otherwise an error is thrown.
*
* @example
* ```typescript
* // Example usage of configSet method to set multiple configuration parameters
* const result = await client.configSet({ timeout: "1000", maxmemory: "1GB" });
* console.log(result); // Output: 'OK'
* ```
*/
async configSet(parameters, options) {
return this.createWritePromise((0, Commands_1.createConfigSet)(parameters), {
decoder: BaseClient_1.Decoder.String,
...options,
});
}
/**
* Echoes the provided `message` back.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/echo/|valkey.io} for details.
*
* @param message - The message to be echoed back.
* @param options - (Optional) See {@link RouteOption} and {@link DecoderOption}.
* @returns The provided `message`. When specifying a route other than a single node,
* it returns a dictionary where each address is the key and its corresponding node response is the value.
*
* @example
* ```typescript
* // Example usage of the echo command
* const echoedMessage = await client.echo("valkey-glide");
* console.log(echoedMessage); // Output: "valkey-glide"
* ```
* @example
* ```typescript
* // Example usage of the echo command with routing to all nodes
* const echoedMessage = await client.echo("valkey-glide", "allNodes");
* console.log(echoedMessage); // Output: {'addr': 'valkey-glide', 'addr2': 'valkey-glide', 'addr3': 'valkey-glide'}
* ```
*/
async echo(message, options) {
return this.createWritePromise((0, Commands_1.createEcho)(message), options).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Returns the server time.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/time/|valkey.io} for details.
*
* @param options - (Optional) See {@link RouteOption}.
*
* @returns The current server time as an `array` with two items:
* - A Unix timestamp,
* - The amount of microseconds already elapsed in the current second.
*
* When specifying a route other than a single node, it returns a dictionary where each address is the key and
* its corresponding node response is the value.
*
* @example
* ```typescript
* // Example usage of time method without any argument
* const result = await client.time();
* console.log(result); // Output: ['1710925775', '913580']
* ```
*
* @example
* ```typescript
* // Example usage of time method with routing to all nodes
* const result = await client.time('allNodes');
* console.log(result); // Output: {'addr': ['1710925775', '913580'], 'addr2': ['1710925775', '913580'], 'addr3': ['1710925775', '913580']}
* ```
*/
async time(options) {
return this.createWritePromise((0, Commands_1.createTime)(), options).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Displays a piece of generative computer art and the server version.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/lolwut/|valkey.io} for details.
*
* @param options - (Optional) The LOLWUT options - see {@link LolwutOptions} and {@link RouteOption}.
* @returns A piece of generative computer art along with the current server version.
*
* @example
* ```typescript
* const response = await client.lolwut({ version: 6, parameters: [40, 20] }, "allNodes");
* console.log(response); // Output: "Valkey ver. 7.2.3" - Indicates the current server version.
* ```
*/
async lolwut(options) {
return this.createWritePromise((0, Commands_1.createLolwut)(options), options).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Invokes a previously loaded function.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/fcall/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param func - The function name.
* @param args - A list of `function` arguments and it should not represent names of keys.
* @param options - (Optional) See {@link RouteOption} and {@link DecoderOption}.
* @returns The invoked function's return value.
*
* @example
* ```typescript
* const response = await client.fcallWithRoute("Deep_Thought", [], "randomNode");
* console.log(response); // Output: Returns the function's return value.
* ```
*/
async fcallWithRoute(func, args, options) {
return this.createWritePromise((0, Commands_1.createFCall)(func, [], args), options).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Invokes a previously loaded read-only function.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/fcall/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param func - The function name.
* @param args - A list of `function` arguments and it should not represent names of keys.
* @param options - (Optional) See {@link RouteOption} and {@link DecoderOption}.
* @returns The invoked function's return value.
*
* @example
* ```typescript
* const response = await client.fcallReadonlyWithRoute("Deep_Thought", ["Answer", "to", "the", "Ultimate",
* "Question", "of", "Life,", "the", "Universe,", "and", "Everything"], "randomNode");
* console.log(response); // Output: 42 # The return value on the function that was execute.
* ```
*/
async fcallReadonlyWithRoute(func, args, options) {
return this.createWritePromise((0, Commands_1.createFCallReadOnly)(func, [], args), options).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Deletes a library and all its functions.
*
* @see {@link https://valkey.io/commands/function-delete/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param libraryCode - The library name to delete.
* @param route - (Optional) The command will be routed to all primary node, unless `route` is provided, in which
* case the client will route the command to the nodes defined by `route`.
* @returns A simple `"OK"` response.
*
* @example
* ```typescript
* const result = await client.functionDelete("libName");
* console.log(result); // Output: 'OK'
* ```
*/
async functionDelete(libraryCode, options) {
return this.createWritePromise((0, Commands_1.createFunctionDelete)(libraryCode), {
decoder: BaseClient_1.Decoder.String,
...options,
});
}
/**
* Loads a library to Valkey.
*
* @see {@link https://valkey.io/commands/function-load/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param libraryCode - The source code that implements the library.
* @param options - (Optional) Additional parameters:
* - (Optional) `replace`: whether the given library should overwrite a library with the same name if it
* already exists.
* - (Optional) `route`: see {@link RouteOption}.
* - (Optional) `decoder`: see {@link DecoderOption}.
* @returns The library name that was loaded.
*
* @example
* ```typescript
* const code = "#!lua name=mylib \n redis.register_function('myfunc', function(keys, args) return args[1] end)";
* const result = await client.functionLoad(code, { replace: true, route: 'allNodes' });
* console.log(result); // Output: 'mylib'
* ```
*/
async functionLoad(libraryCode, options) {
return this.createWritePromise((0, Commands_1.createFunctionLoad)(libraryCode, options?.replace), options);
}
/**
* Deletes all function libraries.
*
* @see {@link https://valkey.io/commands/function-flush/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param options - (Optional) Additional parameters:
* - (Optional) `mode`: the flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
* - (Optional) `route`: see {@link RouteOption}.
* @returns A simple `"OK"` response.
*
* @example
* ```typescript
* const result = await client.functionFlush(FlushMode.SYNC);
* console.log(result); // Output: 'OK'
* ```
*/
async functionFlush(options) {
return this.createWritePromise((0, Commands_1.createFunctionFlush)(options?.mode), {
decoder: BaseClient_1.Decoder.String,
...options,
});
}
/**
* Returns information about the functions and libraries.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/function-list/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param options - (Optional) See {@link FunctionListOptions}, {@link DecoderOption}, and {@link RouteOption}.
* @returns Info about all or selected libraries and their functions in {@link FunctionListResponse} format.
*
* @example
* ```typescript
* // Request info for specific library including the source code
* const result1 = await client.functionList({ libNamePattern: "myLib*", withCode: true });
* // Request info for all libraries
* const result2 = await client.functionList();
* console.log(result2); // Output:
* // [{
* // "library_name": "myLib5_backup",
* // "engine": "LUA",
* // "functions": [{
* // "name": "myfunc",
* // "description": null,
* // "flags": [ "no-writes" ],
* // }],
* // "library_code": "#!lua name=myLib5_backup \n redis.register_function('myfunc', function(keys, args) return args[1] end)"
* // }]
* ```
*/
async functionList(options) {
return this.createWritePromise((0, Commands_1.createFunctionList)(options), options).then((res) => res.length == 0
? res // no libs
: (Array.isArray(res[0])
? // single node response
res.map(BaseClient_1.convertGlideRecordToRecord)
: // multi node response
(0, BaseClient_1.convertGlideRecordToRecord)(res)));
}
/**
* Returns information about the function that's currently running and information about the
* available execution engines.
*
* The command will be routed to all nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/function-stats/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param options - (Optional) See {@link DecoderOption} and {@link RouteOption}.
* @returns A `Record` with two keys:
* - `"running_script"` with information about the running script.
* - `"engines"` with information about available engines and their stats.
* - See example for more details.
*
* @example
* ```typescript
* const response = await client.functionStats("randomNode");
* console.log(response); // Output:
* // {
* // "running_script":
* // {
* // "name": "deep_thought",
* // "command": ["fcall", "deep_thought", "0"],
* // "duration_ms": 5008
* // },
* // "engines":
* // {
* // "LUA":
* // {
* // "libraries_count": 2,
* // "functions_count": 3
* // }
* // }
* // }
* // Output if no scripts running:
* // {
* // "running_script": null
* // "engines":
* // {
* // "LUA":
* // {
* // "libraries_count": 2,
* // "functions_count": 3
* // }
* // }
* // }
* ```
*/
async functionStats(options) {
return this.createWritePromise((0, Commands_1.createFunctionStats)(), options).then((res) => (0, BaseClient_1.convertGlideRecordToRecord)(res));
}
/**
* Kills a function that is currently executing.
* `FUNCTION KILL` terminates read-only functions only.
*
* @see {@link https://valkey.io/commands/function-kill/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param options - (Optional) See {@link RouteOption}.
* @returns `"OK"` if function is terminated. Otherwise, throws an error.
*
* @example
* ```typescript
* await client.functionKill();
* ```
*/
async functionKill(options) {
return this.createWritePromise((0, Commands_1.createFunctionKill)(), {
decoder: BaseClient_1.Decoder.String,
...options,
});
}
/**
* Returns the serialized payload of all loaded libraries.
*
* @see {@link https://valkey.io/commands/function-dump/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param options - (Optional) See {@link RouteOption}.
* @returns The serialized payload of all loaded libraries.
*
* @example
* ```typescript
* const data = await client.functionDump();
* // data can be used to restore loaded functions on any Valkey instance
* ```
*/
async functionDump(options) {
return this.createWritePromise((0, Commands_1.createFunctionDump)(), { decoder: BaseClient_1.Decoder.Bytes, ...options }).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Restores libraries from the serialized payload returned by {@link functionDump}.
*
* @see {@link https://valkey.io/commands/function-restore/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param payload - The serialized data from {@link functionDump}.
* @param options - (Optional) Additional parameters:
* - (Optional) `policy`: a policy for handling existing libraries, see {@link FunctionRestorePolicy}.
* {@link FunctionRestorePolicy.APPEND} is used by default.
* - (Optional) `route`: see {@link RouteOption}.
* @returns `"OK"`.
*
* @example
* ```typescript
* await client.functionRestore(data, { policy: FunctionRestorePolicy.FLUSH, route: "allPrimaries" });
* ```
*/
async functionRestore(payload, options) {
return this.createWritePromise((0, Commands_1.createFunctionRestore)(payload, options?.policy), { decoder: BaseClient_1.Decoder.String, ...options });
}
/**
* Deletes all the keys of all the existing databases. This command never fails.
*
* The command will be routed to all primary nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/flushall/|valkey.io} for details.
*
* @param options - (Optional) Additional parameters:
* - (Optional) `mode`: the flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
* - (Optional) `route`: see {@link RouteOption}.
* @returns `OK`.
*
* @example
* ```typescript
* const result = await client.flushall(FlushMode.SYNC);
* console.log(result); // Output: 'OK'
* ```
*/
async flushall(options) {
return this.createWritePromise((0, Commands_1.createFlushAll)(options?.mode), {
decoder: BaseClient_1.Decoder.String,
...options,
});
}
/**
* Deletes all the keys of the currently selected database. This command never fails.
*
* The command will be routed to all primary nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/flushdb/|valkey.io} for details.
*
* @param options - (Optional) Additional parameters:
* - (Optional) `mode`: the flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
* - (Optional) `route`: see {@link RouteOption}.
* @returns `OK`.
*
* @example
* ```typescript
* const result = await client.flushdb(FlushMode.SYNC);
* console.log(result); // Output: 'OK'
* ```
*/
async flushdb(options) {
return this.createWritePromise((0, Commands_1.createFlushDB)(options?.mode), {
decoder: BaseClient_1.Decoder.String,
...options,
});
}
/**
* Returns the number of keys in the database.
*
* The command will be routed to all nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/dbsize/|valkey.io} for details.
*
* @param options - (Optional) See {@link RouteOption}.
* @returns The number of keys in the database.
* In the case of routing the query to multiple nodes, returns the aggregated number of keys across the different nodes.
*
* @example
* ```typescript
* const numKeys = await client.dbsize("allPrimaries");
* console.log("Number of keys across all primary nodes: ", numKeys);
* ```
*/
async dbsize(options) {
return this.createWritePromise((0, Commands_1.createDBSize)(), options);
}
/** Publish a message on pubsub channel.
* This command aggregates PUBLISH and SPUBLISH commands functionalities.
* The mode is selected using the 'sharded' parameter.
* For both sharded and non-sharded mode, request is routed using hashed channel as key.
*
* @see {@link https://valkey.io/commands/publish} and {@link https://valkey.io/commands/spublish} for more details.
*
* @param message - Message to publish.
* @param channel - Channel to publish the message on.
* @param sharded - Use sharded pubsub mode. Available since Valkey version 7.0.
* @returns - Number of subscriptions in primary node that received the message.
*
* @example
* ```typescript
* // Example usage of publish command
* const result = await client.publish("Hi all!", "global-channel");
* console.log(result); // Output: 1 - This message was posted to 1 subscription which is configured on primary node
* ```
*
* @example
* ```typescript
* // Example usage of spublish command
* const result = await client.publish("Hi all!", "global-channel", true);
* console.log(result); // Output: 2 - Published 2 instances of "Hi to sharded channel1!" message on channel1 using sharded mode
* ```
*/
async publish(message, channel, sharded = false) {
return this.createWritePromise((0, Commands_1.createPublish)(message, channel, sharded));
}
/**
* Lists the currently active shard channels.
* The command is routed to all nodes, and aggregates the response to a single array.
*
* @see {@link https://valkey.io/commands/pubsub-shardchannels/|valkey.io} for details.
*
* @param options - (Optional) Additional parameters:
* - (Optional) `pattern`: A glob-style pattern to match active shard channels.
* If not provided, all active shard channels are returned.
* - (Optional) `decoder`: see {@link DecoderOption}.
* @returns A list of currently active shard channels matching the given pattern.
* If no pattern is specified, all active shard channels are returned.
*
* @example
* ```typescript
* const allChannels = await client.pubsubShardchannels();
* console.log(allChannels); // Output: ["channel1", "channel2"]
*
* const filteredChannels = await client.pubsubShardchannels("channel*");
* console.log(filteredChannels); // Output: ["channel1", "channel2"]
* ```
*/
async pubsubShardChannels(options) {
return this.createWritePromise((0, Commands_1.createPubsubShardChannels)(options?.pattern), options);
}
/**
* Returns the number of subscribers (exclusive of clients subscribed to patterns) for the specified shard channels.
*
* @see {@link https://valkey.io/commands/pubsub-shardnumsub/|valkey.io} for details.
* @remarks The command is routed to all nodes, and aggregates the response into a single list.
*
* @param channels - The list of shard channels to query for the number of subscribers.
* @param options - (Optional) see {@link DecoderOption}.
* @returns A list of the shard channel names and their numbers of subscribers.
*
* @example
* ```typescript
* const result1 = await client.pubsubShardnumsub(["channel1", "channel2"]);
* console.log(result1); // Output:
* // [{ channel: "channel1", numSub: 3}, { channel: "channel2", numSub: 5 }]
*
* const result2 = await client.pubsubShardnumsub([]);
* console.log(result2); // Output: []
* ```
*/
async pubsubShardNumSub(channels, options) {
return this.createWritePromise((0, Commands_1.createPubSubShardNumSub)(channels), options).then((res) => res.map((r) => {
return { channel: r.key, numSub: r.value };
}));
}
/**
* Returns `UNIX TIME` of the last DB save timestamp or startup timestamp if no save
* was made since then.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/lastsave/|valkey.io} for details.
*
* @param options - (Optional) See {@link RouteOption}.
* @returns `UNIX TIME` of the last DB save executed with success.
*
* @example
* ```typescript
* const timestamp = await client.lastsave();
* console.log("Last DB save was done at " + timestamp);
* ```
*/
async lastsave(options) {
return this.createWritePromise((0, Commands_1.createLastSave)(), options).then((res) => convertClusterGlideRecord(res, true, options?.route));
}
/**
* Returns a random existing key name.
*
* The command will be routed to all primary nodes, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/randomkey/|valkey.io} for details.
*
* @param options - (Optional) See {@link RouteOption} and {@link DecoderOption}.
* @returns A random existing key name.
*