From 9f14540d290fb2c4d198c73c8afbf04ca4f67290 Mon Sep 17 00:00:00 2001 From: AgentEnder Date: Wed, 28 Feb 2024 15:27:44 -0500 Subject: [PATCH] fix(core): plugins should not be registered twice and should respect shutdown queue --- .../src/project-graph/plugins/internal-api.ts | 10 +-- .../src/project-graph/plugins/plugin-pool.ts | 62 +++++++++++-------- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/packages/nx/src/project-graph/plugins/internal-api.ts b/packages/nx/src/project-graph/plugins/internal-api.ts index de55fa1567291..8cb558638b91f 100644 --- a/packages/nx/src/project-graph/plugins/internal-api.ts +++ b/packages/nx/src/project-graph/plugins/internal-api.ts @@ -44,7 +44,7 @@ export type RemotePlugin = // holding resolved nx plugin objects. // Allows loaded plugins to not be reloaded when // referenced multiple times. -export const nxPluginCache: Map = new Map(); +export const nxPluginCache: Map> = new Map(); export async function loadNxPlugins( plugins: PluginConfiguration[], @@ -78,12 +78,12 @@ export async function loadNxPlugin( const cacheKey = JSON.stringify(plugin); if (nxPluginCache.has(cacheKey)) { - return nxPluginCache.get(cacheKey)!; + return await nxPluginCache.get(cacheKey)!; } - const loadedPlugin = await loadRemoteNxPlugin(plugin, root); - nxPluginCache.set(cacheKey, loadedPlugin); - return loadedPlugin; + const loadingPlugin = loadRemoteNxPlugin(plugin, root); + nxPluginCache.set(cacheKey, loadingPlugin); + return await loadingPlugin; } export async function getDefaultPlugins(root: string) { diff --git a/packages/nx/src/project-graph/plugins/plugin-pool.ts b/packages/nx/src/project-graph/plugins/plugin-pool.ts index 340bce5a02f9b..03bc400612d4b 100644 --- a/packages/nx/src/project-graph/plugins/plugin-pool.ts +++ b/packages/nx/src/project-graph/plugins/plugin-pool.ts @@ -121,61 +121,43 @@ function createWorkerHandler( ? [ createNodesPattern, (configFiles, ctx) => { - return new Promise(function (res, rej) { - const tx = - pluginName + ':createNodes:' + performance.now(); + const tx = pluginName + ':createNodes:' + performance.now(); + return registerPendingPromise(tx, pending, () => { worker.send( createMessage({ type: 'createNodes', payload: { configFiles, context: ctx, tx }, }) ); - pending.add(tx); - promiseBank.set(tx, { - promise: this, - resolver: res, - rejecter: rej, - }); }); }, ] : undefined, createDependencies: result.hasCreateDependencies ? (opts, ctx) => { - return new Promise(function (res, rej) { - const tx = pluginName + ':createNodes:' + performance.now(); + const tx = + pluginName + ':createDependencies:' + performance.now(); + return registerPendingPromise(tx, pending, () => { worker.send( createMessage({ type: 'createDependencies', payload: { context: ctx, tx }, }) ); - pending.add(tx); - promiseBank.set(tx, { - promise: this, - resolver: res, - rejecter: rej, - }); }); } : undefined, processProjectGraph: result.hasProcessProjectGraph ? (graph, ctx) => { - return new Promise(function (res, rej) { - const tx = - pluginName + ':processProjectGraph:' + performance.now(); + const tx = + pluginName + ':processProjectGraph:' + performance.now(); + return registerPendingPromise(tx, pending, () => { worker.send( createMessage({ type: 'processProjectGraph', payload: { graph, ctx, tx }, }) ); - pending.add(tx); - promiseBank.set(tx, { - promise: this, - resolver: res, - rejecter: rej, - }); }); } : undefined, @@ -255,3 +237,31 @@ function getPendingPromises( } return pendingTxs; } + +function registerPendingPromise( + tx: string, + pending: Set, + callback: () => void +): Promise { + let resolver, rejecter; + + const promise = new Promise((res, rej) => { + resolver = res; + rejecter = rej; + + callback(); + }).then((val) => { + // Remove the promise from the pending set + pending.delete(tx); + // Return the original value + return val; + }); + + pending.add(tx); + promiseBank.set(tx, { + promise, + resolver, + rejecter, + }); + return promise; +}