feat(xapi/call{,Async}): retry if too many pending tasks

Logic from xo-server/xapi/call
This commit is contained in:
Julien Fontanet 2021-03-30 14:21:19 +02:00
parent 594a148a39
commit 3bb7d2c294
3 changed files with 31 additions and 15 deletions

View File

@ -1,5 +1,6 @@
const assert = require('assert')
const defer = require('promise-toolbox/defer')
const pRetry = require('promise-toolbox/retry')
const { utcFormat, utcParse } = require('d3-time-format')
const { Xapi: Base } = require('xen-api')
@ -34,10 +35,22 @@ const hasProps = o => {
}
class Xapi extends Base {
constructor({ ignoreNobakVdis, maxUncoalescedVdis, vdiDestroyRetryWhenInUse, ...opts }) {
constructor({
callRetryWhenTooManyPendingTasks,
ignoreNobakVdis,
maxUncoalescedVdis,
vdiDestroyRetryWhenInUse,
...opts
}) {
assert.notStrictEqual(ignoreNobakVdis, undefined)
super(opts)
this._callRetryWhenTooManyPendingTasks = {
delay: 5e3,
tries: 10,
...callRetryWhenTooManyPendingTasks,
when: { code: 'TOO_MANY_PENDING_TASKS' },
}
this._ignoreNobakVdis = ignoreNobakVdis
this._maxUncoalescedVdis = maxUncoalescedVdis
this._vdiDestroyRetryWhenInUse = {
@ -124,3 +137,17 @@ mixin({
VM: require('./vm'),
})
exports.Xapi = Xapi
// TODO: remove once using next promise-toolbox
function pRetryWrap(fn, options) {
const getOptions = typeof options !== 'function' ? () => options : options
return function () {
return pRetry.call(() => fn.apply(this, arguments), getOptions.apply(this, arguments))
}
}
function getCallRetryOpts() {
return this._callRetryWhenTooManyPendingTasks
}
Xapi.prototype.call = pRetryWrap(Xapi.prototype.call, getCallRetryOpts)
Xapi.prototype.callAsync = pRetryWrap(Xapi.prototype.callAsync, getCallRetryOpts)

View File

@ -23,3 +23,6 @@
> - major: if the change breaks compatibility
>
> In case of conflict, the highest (lowest in previous list) `$version` wins.
- @xen-orchestra/xapi minor
- xo-server patch

View File

@ -126,20 +126,6 @@ export default class Xapi extends XapiBase {
this.objects.on('update', onAddOrUpdate)
}
call(...args) {
const fn = super.call
const loop = () =>
fn.apply(this, args)::pCatch(
{
code: 'TOO_MANY_PENDING_TASKS',
},
() => pDelay(5e3).then(loop)
)
return loop()
}
// =================================================================
_registerGenericWatcher(fn) {