diff --git a/@xen-orchestra/babel-config/index.js b/@xen-orchestra/babel-config/index.js index a42790afb..4ea24f9c0 100644 --- a/@xen-orchestra/babel-config/index.js +++ b/@xen-orchestra/babel-config/index.js @@ -46,6 +46,12 @@ const getConfig = (key, ...args) => { : config } +// some plugins must be used in a specific order +const pluginsOrder = [ + '@babel/plugin-proposal-decorators', + '@babel/plugin-proposal-class-properties', +] + module.exports = function(pkg, plugins, presets) { plugins === undefined && (plugins = {}) presets === undefined && (presets = {}) @@ -61,7 +67,13 @@ module.exports = function(pkg, plugins, presets) { return { comments: !__PROD__, ignore: __TEST__ ? undefined : [/\.spec\.js$/], - plugins: Object.keys(plugins).map(plugin => [plugin, plugins[plugin]]), + plugins: Object.keys(plugins) + .map(plugin => [plugin, plugins[plugin]]) + .sort(([a], [b]) => { + const oA = pluginsOrder.indexOf(a) + const oB = pluginsOrder.indexOf(b) + return oA !== -1 && oB !== -1 ? oA - oB : a < b ? -1 : 1 + }), presets: Object.keys(presets).map(preset => [preset, presets[preset]]), } } diff --git a/packages/xen-api/package.json b/packages/xen-api/package.json index 36e244fef..133622255 100644 --- a/packages/xen-api/package.json +++ b/packages/xen-api/package.json @@ -54,6 +54,7 @@ "devDependencies": { "@babel/cli": "^7.0.0", "@babel/core": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.3.4", "@babel/plugin-proposal-decorators": "^7.0.0", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.2.0", "@babel/plugin-proposal-optional-chaining": "^7.2.0", diff --git a/packages/xen-api/src/_coalesceCalls.js b/packages/xen-api/src/_coalesceCalls.js new file mode 100644 index 000000000..c288cc914 --- /dev/null +++ b/packages/xen-api/src/_coalesceCalls.js @@ -0,0 +1,15 @@ +// decorates fn so that more than one concurrent calls will be coalesced +export default function coalesceCalls(fn) { + let promise + const clean = () => { + promise = undefined + } + return function() { + if (promise !== undefined) { + return promise + } + promise = fn.apply(this, arguments) + promise.then(clean, clean) + return promise + } +} diff --git a/packages/xen-api/src/_coalesceCalls.spec.js b/packages/xen-api/src/_coalesceCalls.spec.js new file mode 100644 index 000000000..b39d8a79f --- /dev/null +++ b/packages/xen-api/src/_coalesceCalls.spec.js @@ -0,0 +1,26 @@ +/* eslint-env jest */ + +import pDefer from 'promise-toolbox/defer' + +import coalesceCalls from './_coalesceCalls' + +describe('coalesceCalls', () => { + it('decorates an async function', async () => { + const fn = coalesceCalls(promise => promise) + + const defer1 = pDefer() + const promise1 = fn(defer1.promise) + const defer2 = pDefer() + const promise2 = fn(defer2.promise) + + defer1.resolve('foo') + expect(await promise1).toBe('foo') + expect(await promise2).toBe('foo') + + const defer3 = pDefer() + const promise3 = fn(defer3.promise) + + defer3.resolve('bar') + expect(await promise3).toBe('bar') + }) +}) diff --git a/packages/xen-api/src/index.js b/packages/xen-api/src/index.js index 68798e36b..fb802095c 100644 --- a/packages/xen-api/src/index.js +++ b/packages/xen-api/src/index.js @@ -26,6 +26,7 @@ import { } from 'promise-toolbox' import autoTransport from './transports/auto' +import coalesceCalls from './_coalesceCalls' import debug from './_debug' import getTaskResult from './_getTaskResult' import isGetAllRecordsMethod from './_isGetAllRecordsMethod' @@ -201,6 +202,7 @@ export class Xapi extends EventEmitter { return id ? (id === CONNECTING ? CONNECTING : CONNECTED) : DISCONNECTED } + connect = coalesceCalls(this.connect) async connect() { const { status } = this diff --git a/yarn.lock b/yarn.lock index 1996c2990..0aca441ce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -256,6 +256,14 @@ "@babel/helper-remap-async-to-generator" "^7.1.0" "@babel/plugin-syntax-async-generators" "^7.2.0" +"@babel/plugin-proposal-class-properties@^7.3.4": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.4.0.tgz#d70db61a2f1fd79de927eea91f6411c964e084b8" + integrity sha512-t2ECPNOXsIeK1JxJNKmgbzQtoG27KIlVE61vTqX0DKR9E9sZlVVxWUtEW9D5FlZ8b8j7SBNCHY47GgPKCKlpPg== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.4.0" + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-decorators@^7.0.0", "@babel/plugin-proposal-decorators@^7.1.6": version "7.4.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.4.0.tgz#8e1bfd83efa54a5f662033afcc2b8e701f4bb3a9"