forked from valkey-io/valkey-glide
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Node: add node cluster mode and standalone examples (valkey-io#2357)
* Node: add node cluster mode example Signed-off-by: Adar Ovadia <adarov@amazon.com> --------- Signed-off-by: Adar Ovadia <adarov@amazon.com> Co-authored-by: Adar Ovadia <adarov@amazon.com>
- Loading branch information
1 parent
2c7ec4d
commit 2510ab9
Showing
4 changed files
with
293 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/** | ||
* Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 | ||
*/ | ||
|
||
import { | ||
ClosingError, | ||
ConnectionError, | ||
GlideClusterClient, | ||
InfoOptions, | ||
Logger, | ||
RequestError, | ||
TimeoutError, | ||
} from "@valkey/valkey-glide"; | ||
|
||
/** | ||
* Creates and returns a GlideClusterClient instance. | ||
* This function initializes a GlideClusterClient with the provided list of nodes. | ||
* The nodesList may contain the address of one or more cluster nodes, and the | ||
* client will automatically discover all nodes in the cluster. | ||
* @param nodesList A list of tuples where each tuple contains a host (str) and port (int). Defaults to [("localhost", 6379)]. | ||
* @returns An instance of GlideClusterClient connected to the discovered nodes. | ||
*/ | ||
async function createClient(nodesList = [{ host: "localhost", port: 6379 }]) { | ||
const addresses = nodesList.map((node) => ({ | ||
host: node.host, | ||
port: node.port, | ||
})); | ||
|
||
// Check `GlideClusterClientConfiguration` for additional options. | ||
return await GlideClusterClient.createClient({ | ||
addresses: addresses, | ||
// if the server uses TLS, you'll need to enable it. Otherwise the connection attempt will time out silently. | ||
// useTLS: true, | ||
}); | ||
} | ||
|
||
/** | ||
* Executes the main logic of the application, performing basic operations | ||
* such as SET, GET, PING, and INFO REPLICATION using the provided GlideClusterClient. | ||
* @param client An instance of GlideClusterClient. | ||
*/ | ||
async function appLogic(client: GlideClusterClient) { | ||
// Send SET and GET | ||
const setResponse = await client.set("foo", "bar"); | ||
Logger.log("info", "app", `Set response is: ${setResponse}`); | ||
|
||
const getResponse = await client.get("foo"); | ||
Logger.log("info", "app", `Get response is: ${getResponse?.toString()}`); | ||
|
||
// Send PING to all primaries (according to Redis's PING request_policy) | ||
const pong = await client.ping(); | ||
Logger.log("info", "app", `PING response: ${pong}`); | ||
|
||
// Send INFO REPLICATION to all nodes | ||
const infoReplResps = await client.info({ | ||
sections: [InfoOptions.Replication], | ||
}); | ||
const infoReplicationValues = Object.values(infoReplResps); | ||
|
||
Logger.log( | ||
"info", | ||
"app", | ||
`INFO REPLICATION responses from all nodes are:\n`, | ||
); | ||
|
||
infoReplicationValues.forEach((item) => | ||
Logger.log("info", "glide", item as string), | ||
); | ||
} | ||
|
||
/** | ||
* Executes the application logic with exception handling. | ||
*/ | ||
async function execAppLogic() { | ||
// Loop through with exception handling | ||
while (true) { | ||
let client; | ||
|
||
try { | ||
client = await createClient(); | ||
return await appLogic(client); | ||
} catch (error) { | ||
switch (true) { | ||
case error instanceof ClosingError: | ||
// If the error message contains "NOAUTH", raise the exception | ||
// because it indicates a critical authentication issue. | ||
if ((error as ClosingError).message.includes("NOAUTH")) { | ||
Logger.log( | ||
"error", | ||
"glide", | ||
`Authentication error encountered: ${error}`, | ||
); | ||
} else { | ||
Logger.log( | ||
"warn", | ||
"glide", | ||
`Client has closed and needs to be re-created: ${error}`, | ||
); | ||
} | ||
|
||
throw error; | ||
case error instanceof TimeoutError: | ||
// A request timed out. You may choose to retry the execution based on your application's logic | ||
Logger.log("error", "glide", `Timeout error: ${error}`); | ||
throw error; | ||
case error instanceof ConnectionError: | ||
// The client wasn't able to reestablish the connection within the given retries | ||
Logger.log("error", "glide", `Connection error: ${error}`); | ||
throw error; | ||
case error instanceof RequestError: | ||
// Other error reported during a request, such as a server response error | ||
Logger.log( | ||
"error", | ||
"glide", | ||
`RequestError encountered: ${error}`, | ||
); | ||
throw error; | ||
default: | ||
Logger.log("error", "glide", `Unexpected error: ${error}`); | ||
throw error; | ||
} | ||
} finally { | ||
try { | ||
if (client) { | ||
await client.close(); | ||
} | ||
} catch (error) { | ||
Logger.log( | ||
"warn", | ||
"glide", | ||
`Error encountered while closing the client: ${error}`, | ||
); | ||
} | ||
} | ||
} | ||
} | ||
|
||
function main() { | ||
// In this example, we will utilize the client's logger for all log messages | ||
Logger.setLoggerConfig("info"); | ||
// Optional - set the logger to write to a file | ||
// Logger.setLoggerConfig("info", fileName); | ||
execAppLogic(); | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/** | ||
* Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 | ||
*/ | ||
|
||
import { | ||
ClosingError, | ||
ConnectionError, | ||
GlideClient, | ||
Logger, | ||
RequestError, | ||
TimeoutError, | ||
} from "@valkey/valkey-glide"; | ||
|
||
/** | ||
* Creates and returns a GlideClient instance. | ||
* This function initializes a GlideClient with the provided list of nodes. | ||
* The nodes_list may contain either only primary node or a mix of primary | ||
* and replica nodes. The GlideClient use these nodes to connect to | ||
* the Standalone setup servers. | ||
* @param nodesList A list of tuples where each tuple contains a host (str) and port (int). Defaults to [("localhost", 6379)]. | ||
* @returns An instance of GlideClient connected to the discovered nodes. | ||
*/ | ||
async function createClient(nodesList = [{ host: "localhost", port: 6379 }]) { | ||
const addresses = nodesList.map((node) => ({ | ||
host: node.host, | ||
port: node.port, | ||
})); | ||
|
||
// Check `GlideClientConfiguration` for additional options. | ||
return await GlideClient.createClient({ | ||
addresses: addresses, | ||
// if the server uses TLS, you'll need to enable it. Otherwise the connection attempt will time out silently. | ||
// useTLS: true, | ||
}); | ||
} | ||
|
||
/** | ||
* Executes the main logic of the application, performing basic operations | ||
* such as SET, GET, PING, and INFO REPLICATION using the provided GlideClient. | ||
* @param client An instance of GlideClient. | ||
*/ | ||
async function appLogic(client: GlideClient) { | ||
// Send SET and GET | ||
const setResponse = await client.set("foo", "bar"); | ||
Logger.log("info", "app", `Set response is: ${setResponse}`); | ||
|
||
const getResponse = await client.get("foo"); | ||
Logger.log("info", "app", `Get response is: ${getResponse?.toString()}`); | ||
|
||
// Send PING to primary | ||
const pong = await client.ping(); | ||
Logger.log("info", "app", `PING response: ${pong}`); | ||
} | ||
|
||
/** | ||
* Executes the application logic with exception handling. | ||
*/ | ||
async function execAppLogic() { | ||
// Loop through with exception handling | ||
while (true) { | ||
let client; | ||
|
||
try { | ||
client = await createClient(); | ||
return await appLogic(client); | ||
} catch (error) { | ||
switch (true) { | ||
case error instanceof ClosingError: | ||
// If the error message contains "NOAUTH", raise the exception | ||
// because it indicates a critical authentication issue. | ||
if ((error as ClosingError).message.includes("NOAUTH")) { | ||
Logger.log( | ||
"error", | ||
"glide", | ||
`Authentication error encountered: ${error}`, | ||
); | ||
} else { | ||
Logger.log( | ||
"warn", | ||
"glide", | ||
`Client has closed and needs to be re-created: ${error}`, | ||
); | ||
} | ||
|
||
throw error; | ||
case error instanceof TimeoutError: | ||
// A request timed out. You may choose to retry the execution based on your application's logic | ||
Logger.log("error", "glide", `Timeout error: ${error}`); | ||
throw error; | ||
case error instanceof ConnectionError: | ||
// The client wasn't able to reestablish the connection within the given retries | ||
Logger.log("error", "glide", `Connection error: ${error}`); | ||
throw error; | ||
case error instanceof RequestError: | ||
// Other error reported during a request, such as a server response error | ||
Logger.log( | ||
"error", | ||
"glide", | ||
`RequestError encountered: ${error}`, | ||
); | ||
throw error; | ||
default: | ||
Logger.log("error", "glide", `Unexpected error: ${error}`); | ||
throw error; | ||
} | ||
} finally { | ||
try { | ||
if (client) { | ||
await client.close(); | ||
} | ||
} catch (error) { | ||
Logger.log( | ||
"warn", | ||
"glide", | ||
`Error encountered while closing the client: ${error}`, | ||
); | ||
} | ||
} | ||
} | ||
} | ||
|
||
function main() { | ||
// In this example, we will utilize the client's logger for all log messages | ||
Logger.setLoggerConfig("info"); | ||
// Optional - set the logger to write to a file | ||
// Logger.setLoggerConfig("info", fileName); | ||
execAppLogic(); | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
{ | ||
"devDependencies": { | ||
"@eslint/js": "^9.10.0", | ||
"@types/eslint__js": "^8.42.3", | ||
"@types/eslint-config-prettier": "^6.11.3", | ||
"eslint": "^9.10.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"prettier": "^3.3.3", | ||
"typescript": "^5.6.2", | ||
"typescript-eslint": "^8.5.0" | ||
} | ||
"devDependencies": { | ||
"@eslint/js": "^9.10.0", | ||
"@types/eslint__js": "^8.42.3", | ||
"@types/eslint-config-prettier": "^6.11.3", | ||
"eslint": "^9.10.0", | ||
"eslint-config-prettier": "^9.1.0", | ||
"prettier": "^3.3.3", | ||
"typescript": "^5.6.2", | ||
"typescript-eslint": "^8.5.0" | ||
} | ||
} |