|
@ -9,6 +9,9 @@ module.exports = class RPC { |
|
|
this._tick = 0 |
|
|
this._tick = 0 |
|
|
this._w = 0 |
|
|
this._w = 0 |
|
|
this._win = [0, 0, 0, 0] |
|
|
this._win = [0, 0, 0, 0] |
|
|
|
|
|
this._bind = opts.bind || 0 |
|
|
|
|
|
this._bound = false |
|
|
|
|
|
this._binding = null |
|
|
|
|
|
|
|
|
this.maxWindow = opts.maxWindow || 80 // ~100 per second burst, ~80 per second avg
|
|
|
this.maxWindow = opts.maxWindow || 80 // ~100 per second burst, ~80 per second avg
|
|
|
this.maxRetries = 3 |
|
|
this.maxRetries = 3 |
|
@ -45,31 +48,41 @@ module.exports = class RPC { |
|
|
return this.socket.address() |
|
|
return this.socket.address() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bind (port) { |
|
|
bind (port = this._bind) { |
|
|
return new Promise((resolve, reject) => { |
|
|
if (this._binding) return this._binding |
|
|
const s = this.socket |
|
|
|
|
|
|
|
|
|
|
|
if (s.listen) { |
|
|
const defaultPort = this._bind |
|
|
s.listen(port) |
|
|
|
|
|
} else { |
|
|
this._binding = new Promise((resolve, reject) => { |
|
|
s.bind(port) |
|
|
const s = this.socket |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s.bind(port) |
|
|
s.on('listening', onlistening) |
|
|
s.on('listening', onlistening) |
|
|
s.on('error', onerror) |
|
|
s.on('error', onerror) |
|
|
|
|
|
|
|
|
function onlistening () { |
|
|
function onlistening () { |
|
|
|
|
|
this._bound = true |
|
|
|
|
|
|
|
|
s.removeListener('listening', onlistening) |
|
|
s.removeListener('listening', onlistening) |
|
|
s.removeListener('error', onerror) |
|
|
s.removeListener('error', onerror) |
|
|
resolve() |
|
|
resolve() |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function onerror (err) { |
|
|
function onerror (err) { |
|
|
|
|
|
// retry on any port if preferred port is unavail
|
|
|
|
|
|
if (port === defaultPort && port !== 0) { |
|
|
|
|
|
port = 0 |
|
|
|
|
|
s.bind(0) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
s.removeListener('listening', onlistening) |
|
|
s.removeListener('listening', onlistening) |
|
|
s.removeListener('error', onerror) |
|
|
s.removeListener('error', onerror) |
|
|
reject(err) |
|
|
reject(err) |
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
return this._binding |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
destroy () { |
|
|
destroy () { |
|
@ -93,8 +106,12 @@ module.exports = class RPC { |
|
|
return this.socket |
|
|
return this.socket |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
request (m, opts) { |
|
|
async request (m, opts) { |
|
|
if (this.destroyed) return Promise.reject(new Error('RPC socket destroyed')) |
|
|
if (this.destroyed) throw new Error('RPC socket destroyed') |
|
|
|
|
|
|
|
|
|
|
|
const socket = (opts && opts.socket) || this.socket |
|
|
|
|
|
|
|
|
|
|
|
if (!this._bound && socket === this.socket) await this.bind() |
|
|
|
|
|
|
|
|
if (this._drainInterval === null) { |
|
|
if (this._drainInterval === null) { |
|
|
this._drainInterval = setInterval(this._drain.bind(this), 750) |
|
|
this._drainInterval = setInterval(this._drain.bind(this), 750) |
|
@ -113,7 +130,7 @@ module.exports = class RPC { |
|
|
return new Promise((resolve, reject) => { |
|
|
return new Promise((resolve, reject) => { |
|
|
const total = this._win[0] + this._win[1] + this._win[2] + this._win[3] |
|
|
const total = this._win[0] + this._win[1] + this._win[2] + this._win[3] |
|
|
const req = { |
|
|
const req = { |
|
|
socket: (opts && opts.socket) || this.socket, |
|
|
socket, |
|
|
timeout: 2, |
|
|
timeout: 2, |
|
|
expectOk: !!(opts && opts.expectOk !== false), |
|
|
expectOk: !!(opts && opts.expectOk !== false), |
|
|
tries: (opts && opts.retry === false) ? this.maxRetries : 0, |
|
|
tries: (opts && opts.retry === false) ? this.maxRetries : 0, |
|
|