const BulkTimer = require('./bulk-timer')
const BACKOFF_JITTER = 500
const BACKOFF_S = 1000 + Math.round(BACKOFF_JITTER * Math.random())
const BACKOFF_M = 5000 + Math.round(2 * BACKOFF_JITTER * Math.random())
const BACKOFF_L = 15000 + Math.round(4 * BACKOFF_JITTER * Math.random())
const BACKOFF_X = 1000 * 60 * 10 + Math.round(240 * BACKOFF_JITTER * Math.random())
module.exports = class RetryTimer {
constructor (push, { backoffs = [BACKOFF_S, BACKOFF_M, BACKOFF_L, BACKOFF_X], jitter = BACKOFF_JITTER } = {}) {
this.jitter = jitter
this.backoffs = backoffs
this._sTimer = new BulkTimer(backoffs[0] + Math.round(jitter * Math.random()), push)
this._mTimer = new BulkTimer(backoffs[1] + Math.round(jitter * Math.random()), push)
this._lTimer = new BulkTimer(backoffs[2] + Math.round(jitter * Math.random()), push)
this._xTimer = new BulkTimer(backoffs[3] + Math.round(jitter * Math.random()), push)
}
_selectRetryTimer (peerInfo) {
if (peerInfo.banned || !peerInfo.reconnecting) return null
if (peerInfo.attempts > 3) {
return peerInfo.explicit ? this._xTimer : null
}
if (peerInfo.attempts === 0) return this._sTimer
if (peerInfo.proven) {
switch (peerInfo.attempts) {
case 1: return this._sTimer
case 2: return this._mTimer
case 3: return this._lTimer
}
} else {
switch (peerInfo.attempts) {
case 1: return this._mTimer
case 2: return this._lTimer
case 3: return this._lTimer
}
}
return null
}
add (peerInfo) {
const timer = this._selectRetryTimer(peerInfo)
if (!timer) return false
timer.add(peerInfo)
return true
}
destroy () {
this._sTimer.destroy()
this._mTimer.destroy()
this._lTimer.destroy()
this._xTimer.destroy()
}
}