Skip to content

Commit

Permalink
add a second elasticache connection for dual write
Browse files Browse the repository at this point in the history
  • Loading branch information
zendesk-daniborcas authored and sergionoviello committed May 31, 2024
1 parent 6f70974 commit f9e8dce
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 6 deletions.
27 changes: 24 additions & 3 deletions lib/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function Connection (name, config) {
enableReadyCheck: true
}
this.client = null
this.replicaClient = null
this.subscriber = null
this.readyListeners = []
this.teardownListeners = []
Expand Down Expand Up @@ -63,6 +64,10 @@ Connection.prototype.connectMethod = function (config, callback) {
}
}

Connection.prototype.connectReplicaMethod = function (config, callback) {
this.connectRedis(config.redisReplicaUrl, callback, true)
}

Connection.prototype.establish = function (ready) {
ready = ready || function () {}
const self = this
Expand All @@ -87,6 +92,18 @@ Connection.prototype.establish = function (ready) {
self.client = client
}))

if (process.env.RADAR_MIGRATION_ENABLED === 'true') {
// create a client (read/write)
this.connectReplicaMethod(this.config, tracker('client ready :' + this.name, function (error, replicaClient) {
if (error) {
throw (error instanceof Error) ? error : new Error(error)
}

logging.info('Created new read/write replicaClient client.')
self.replicaClient = replicaClient
}))
}

// create a pubsub client
this.connectMethod(this.config, tracker('subscriber ready :' + this.name, function (error, subscriber) {
if (error) {
Expand Down Expand Up @@ -128,8 +145,8 @@ Connection.prototype.teardown = function (callback) {
}
}

Connection.prototype.connectRedis = function (config, callback) {
var client = new Redis({
Connection.prototype.connectRedis = function (config, callback, isReplica = false) {
let client = new Redis({
port: config.port,
host: config.host,
enableReadyCheck: true,
Expand All @@ -151,7 +168,11 @@ Connection.prototype.connectRedis = function (config, callback) {
}

client.on('ready', function () {
logging.info('Redis client "ready" event.')
if (isReplica) {
logging.info('Redis Replica client "ready" event.')
} else {
logging.info('Redis client "ready" event.')
}
callback(null, client)
})

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "persistence",
"version": "2.1.0",
"version": "2.1.1",
"description": "An abstraction library for redis and sentinel connection management",
"main": "lib/index.js",
"scripts": {
Expand Down
69 changes: 69 additions & 0 deletions test/connection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ const assert = require('assert')
const ConnectionHelper = require('../lib/connection_helper.js')
const SentinelHelper = require('simple_sentinel')

beforeEach(function () {
process.env.RADAR_MIGRATION_ENABLED = 'false'
})

describe('given a ConnectionHelper', function () {
const configuration = {
connection_settings: {
Expand Down Expand Up @@ -104,6 +108,71 @@ describe('given a ConnectionHelper', function () {
})
})

it('should connect to both Redis and Replica', function (done) {
process.env.RADAR_MIGRATION_ENABLED = 'true'
const configurationWithReplica = {
connection_settings: {
main: {
redisReplicaUrl: parseUrl('redis://localhost:26379'),
redis: {
host: 'localhost',
port: 16379
},
sentinel: {
// sentinel master name is required
id: 'mymaster',
sentinels: [
{
host: 'localhost',
port: 26379
},
{
host: 'localhost',
port: 26380
},
{
host: 'localhost',
port: 26381
}]
}
}
}
}
const config = JSON.parse(JSON.stringify(configurationWithReplica))
config.use_connection = 'main'
const connection = ConnectionHelper.connection(config)
connection.establish(function (ready) {
assert.equal(connection.client.status, 'ready')
assert.equal(connection.replicaClient.status, 'ready')
connection.teardown(function () {
ConnectionHelper.destroyConnection(config, done)
})
})
})

function parseUrl (redisUrl) {
const urlParser = require('url')
const parsedUrl = new urlParser.URL(redisUrl)
console.log('parsedUrl: ', parsedUrl)
console.log('hostname: ', parsedUrl.hostname)
console.log('port: ', parsedUrl.port)
const config = {
host: parsedUrl.hostname,
port: parsedUrl.port
}

if (parsedUrl.auth) {
// the password part of user:pass format
config.redis_auth = parsedUrl.auth.substr(parsedUrl.auth.indexOf(':') + 1)
}

if (redisUrl.startsWith('rediss://')) {
config.tls = {}
}

return config
}

it('should reuse existing connection', function (done) {
const config = JSON.parse(JSON.stringify(configuration))
config.use_connection = 'sentinel'
Expand Down

0 comments on commit f9e8dce

Please sign in to comment.