Skip to content

Commit

Permalink
Shuffle connection urls (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbence94 committed Jan 20, 2023
1 parent 8b87170 commit 2b6a568
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/QueueConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class QueueConfig {
rpcQueueMaxSize = 100,
logger = console,

shuffleUrls = false,

// Queue & exchange options
rpcClientAssertReplyQueueOptions = {},
rpcClientExchangeOptions = {},
Expand Down Expand Up @@ -58,6 +60,8 @@ class QueueConfig {
this.rpcQueueMaxSize = rpcQueueMaxSize
this.logger = logger

this.shuffleUrls = shuffleUrls

// Queue & exchange options
this.rpcClientAssertReplyQueueOptions = rpcClientAssertReplyQueueOptions
this.rpcClientExchangeOptions = rpcClientExchangeOptions
Expand Down
9 changes: 9 additions & 0 deletions src/QueueConnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ class QueueConnection extends EventEmitter {
}

async _connectWithMultipleUrls (urls, options) {
if (this._config.shuffleUrls) {
urls = this.shuffleUrls(urls)
}

for (const url of urls) {
const connectionUrl = QueueConfig.urlStringToObject(url)
try {
Expand All @@ -122,6 +126,11 @@ class QueueConnection extends EventEmitter {
throw new Error('RabbitMQ connection filed with multiple urls')
}

shuffleUrls (urls) {
// shuffle urls - try to connect to nodes in a random order
return [...urls].sort((a, b) => 0.5 - Math.random())
}

/**
* @return Promise
* */
Expand Down
28 changes: 28 additions & 0 deletions test/QueueConnection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,34 @@ describe('QueueConnection', () => {
assert.deepEqual(connection._activeConnectionConfig, QueueConfig.urlStringToObject(config.url))
})

it('#shuffleUrls() really shuffles the received urls and QueueConnection can still connect to the correct url', async () => {
const original = ['amqps://random-host:5671', config.url]
const connection = new QueueConnection(copyConfig({
url: original,
shuffleUrls: true
}))

let canDoTheSame = false
let canDoDifferent = false

for (let i = 1; i <= 100 && !(canDoTheSame && canDoDifferent); i++) {
const shuffled = connection.shuffleUrls(original)

if (JSON.stringify(original) === JSON.stringify(shuffled)) {
canDoTheSame = true
} else {
canDoDifferent = true
}
}

// This test failing has a chance of 1 in 2^100 (==1,267,650,600,228,229,401,496,703,205,376)
assert.isTrue(canDoDifferent, 'connect urls shuffle failed to create different order out of a 100 tries')
assert.isTrue(canDoTheSame, 'connect urls shuffle failed to create same order out of a 100 tries')

await connection.connect()
assert.isNotNull(connection._connection)
})

it('#close() closes connection to RabbitMQ', async () => {
const connection = new QueueConnection(config)
try {
Expand Down

0 comments on commit 2b6a568

Please sign in to comment.