feature/IO-2972-Final-Redis-Sockets-Add Redis Cluster aware logic

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-10-07 16:18:11 -04:00
parent c78db7eb08
commit 4be71726d4
5 changed files with 756 additions and 191 deletions

869
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@
"makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\""
},
"dependencies": {
"@aws-sdk/client-elasticache": "^3.665.0",
"@aws-sdk/client-secrets-manager": "^3.654.0",
"@aws-sdk/client-ses": "^3.654.0",
"@aws-sdk/credential-provider-node": "^3.654.0",

View File

@@ -15,6 +15,8 @@ const logger = require("./server/utils/logger");
const { applyRedisHelpers } = require("./server/utils/redisHelpers");
const { applyIOHelpers } = require("./server/utils/ioHelpers");
const { redisSocketEvents } = require("./server/web-sockets/redisSocketEvents");
const { ElastiCacheClient, DescribeCacheClustersCommand } = require("@aws-sdk/client-elasticache");
const { default: InstanceManager } = require("./server/utils/instanceMgr");
// Load environment variables
require("dotenv").config({
@@ -106,18 +108,54 @@ const applyRoutes = ({ app }) => {
});
};
/**
* Fetch Redis nodes from AWS ElastiCache
* @returns {Promise<string[]>}
*/
const getRedisNodesFromAWS = async () => {
const client = new ElastiCacheClient({
region: InstanceManager({
imex: "ca-central-1",
rome: "us-east-2"
})
});
const params = {
ReplicationGroupId: process.env.REDIS_CLUSTER_ID,
ShowCacheNodeInfo: true
};
try {
// Fetch the cache clusters associated with the replication group
const command = new DescribeCacheClustersCommand(params);
const response = await client.send(command);
const cacheClusters = response.CacheClusters;
return cacheClusters.flatMap((cluster) =>
cluster.CacheNodes.map((node) => `${node.Endpoint.Address}:${node.Endpoint.Port}`)
);
} catch (err) {
logger.log(`Error fetching Redis nodes from AWS: ${err.message}`, "ERROR", "redis", "api");
throw err;
}
};
/**
* Connect to Redis Cluster
* @returns {Promise<unknown>}
*/
const connectToRedisCluster = () => {
const connectToRedisCluster = async () => {
let redisServers;
if (isString(process.env?.REDIS_CLUSTER_ID) && !isEmpty(process.env?.REDIS_CLUSTER_ID)) {
// Fetch Redis nodes from AWS if AWS environment variables are present
redisServers = await getRedisNodesFromAWS();
} else {
// Use the Dockerized Redis cluster in development
if (isEmpty(process.env?.REDIS_URL) || !isString(process.env?.REDIS_URL)) {
logger.log(`[${process.env.NODE_ENV}] No or Malformed REDIS_URL present.`, "ERROR", "redis", "api");
process.exit(1);
}
let redisServers;
try {
redisServers = JSON.parse(process.env.REDIS_URL);
} catch (error) {
@@ -129,6 +167,7 @@ const connectToRedisCluster = () => {
);
process.exit(1);
}
}
const clusterRetryStrategy = (times) => {
const delay =

View File

@@ -18,7 +18,7 @@ const ses = new aws.SES({
// The key apiVersion is no longer supported in v3, and can be removed.
// @deprecated The client uses the "latest" apiVersion.
apiVersion: "latest",
defaultProvider,
credentials: defaultProvider(),
region: InstanceManager({
imex: "ca-central-1",
rome: "us-east-2"
@@ -96,7 +96,7 @@ const sendServerEmail = async ({ subject, text }) => {
}
};
const sendProManagerWelcomeEmail = async ({to, subject, html}) => {
const sendProManagerWelcomeEmail = async ({ to, subject, html }) => {
try {
await transporter.sendMail({
from: `ProManager <noreply@promanager.web-est.com>`,

View File

@@ -15,7 +15,7 @@ const { taskEmailQueue } = require("./tasksEmailsQueue");
const ses = new aws.SES({
apiVersion: "latest",
defaultProvider,
credentials: defaultProvider(),
region: InstanceManager({
imex: "ca-central-1",
rome: "us-east-2"