You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.7 KiB
JavaScript
157 lines
4.7 KiB
JavaScript
/*
|
|
* Copyright DataStax, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
'use strict';
|
|
const util = require('util');
|
|
|
|
/** @module policies/reconnection */
|
|
/**
|
|
* Base class for Reconnection Policies
|
|
* @constructor
|
|
*/
|
|
function ReconnectionPolicy() {
|
|
|
|
}
|
|
|
|
/**
|
|
* A new reconnection schedule.
|
|
* @returns {{next: function}} An infinite iterator
|
|
*/
|
|
ReconnectionPolicy.prototype.newSchedule = function () {
|
|
throw new Error('You must implement a new schedule for the Reconnection class');
|
|
};
|
|
|
|
/**
|
|
* Gets an associative array containing the policy options.
|
|
*/
|
|
ReconnectionPolicy.prototype.getOptions = function () {
|
|
return new Map();
|
|
};
|
|
|
|
/**
|
|
* A reconnection policy that waits a constant time between each reconnection attempt.
|
|
* @param {Number} delay Delay in ms
|
|
* @constructor
|
|
*/
|
|
function ConstantReconnectionPolicy(delay) {
|
|
this.delay = delay;
|
|
}
|
|
|
|
util.inherits(ConstantReconnectionPolicy, ReconnectionPolicy);
|
|
|
|
/**
|
|
* A new reconnection schedule that returns the same next delay value
|
|
* @returns {{next: Function}} An infinite iterator
|
|
*/
|
|
ConstantReconnectionPolicy.prototype.newSchedule = function () {
|
|
const self = this;
|
|
return {
|
|
next: function () {
|
|
return {value: self.delay, done: false};
|
|
}
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Gets an associative array containing the policy options.
|
|
*/
|
|
ConstantReconnectionPolicy.prototype.getOptions = function () {
|
|
return new Map([['delay', this.delay ]]);
|
|
};
|
|
|
|
/**
|
|
* A reconnection policy that waits exponentially longer between each
|
|
* reconnection attempt (but keeps a constant delay once a maximum delay is reached).
|
|
* <p>
|
|
* A random amount of jitter (+/- 15%) will be added to the pure exponential delay value to avoid situations
|
|
* where many clients are in the reconnection process at exactly the same time. The jitter will never cause the
|
|
* delay to be less than the base delay, or more than the max delay.
|
|
* </p>
|
|
* @param {Number} baseDelay The base delay in milliseconds to use for the schedules created by this policy.
|
|
* @param {Number} maxDelay The maximum delay in milliseconds to wait between two reconnection attempt.
|
|
* @param {Boolean} startWithNoDelay Determines if the first attempt should be zero delay
|
|
* @constructor
|
|
*/
|
|
function ExponentialReconnectionPolicy(baseDelay, maxDelay, startWithNoDelay) {
|
|
this.baseDelay = baseDelay;
|
|
this.maxDelay = maxDelay;
|
|
this.startWithNoDelay = startWithNoDelay;
|
|
}
|
|
|
|
util.inherits(ExponentialReconnectionPolicy, ReconnectionPolicy);
|
|
|
|
/**
|
|
* A new schedule that uses an exponentially growing delay between reconnection attempts.
|
|
* @returns {{next: Function}} An infinite iterator.
|
|
*/
|
|
ExponentialReconnectionPolicy.prototype.newSchedule = function* () {
|
|
let index = this.startWithNoDelay ? -1 : 0;
|
|
|
|
while (true) {
|
|
let delay = 0;
|
|
|
|
if (index >= 64) {
|
|
delay = this.maxDelay;
|
|
} else if (index !== -1) {
|
|
delay = Math.min(Math.pow(2, index) * this.baseDelay, this.maxDelay);
|
|
}
|
|
|
|
index++;
|
|
|
|
yield this._addJitter(delay);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Adds a random portion of +-15% to the delay provided.
|
|
* Initially, its adds a random value of 15% to avoid reconnection before reaching the base delay.
|
|
* When the schedule reaches max delay, only subtracts a random portion of 15%.
|
|
*/
|
|
ExponentialReconnectionPolicy.prototype._addJitter = function (value) {
|
|
if (value === 0) {
|
|
// Instant reconnection without jitter
|
|
return value;
|
|
}
|
|
|
|
// Use the formula: 85% + rnd() * 30% to calculate the percentage of the original delay
|
|
let minPercentage = 0.85;
|
|
let range = 0.30;
|
|
|
|
if (!this.startWithNoDelay && value === this.baseDelay) {
|
|
// Between 100% to 115% of the original value
|
|
minPercentage = 1;
|
|
range = 0.15;
|
|
} else if (value === this.maxDelay) {
|
|
// Between 85% to 100% of the original value
|
|
range = 0.15;
|
|
}
|
|
|
|
return Math.floor(value * (Math.random() * range + minPercentage));
|
|
};
|
|
|
|
/**
|
|
* Gets an associative array containing the policy options.
|
|
*/
|
|
ExponentialReconnectionPolicy.prototype.getOptions = function () {
|
|
return new Map([
|
|
['baseDelay', this.baseDelay ],
|
|
['maxDelay', this.maxDelay ],
|
|
['startWithNoDelay', this.startWithNoDelay ]
|
|
]);
|
|
};
|
|
|
|
exports.ReconnectionPolicy = ReconnectionPolicy;
|
|
exports.ConstantReconnectionPolicy = ConstantReconnectionPolicy;
|
|
exports.ExponentialReconnectionPolicy = ExponentialReconnectionPolicy; |