diff --git a/packages/yarn-plugin/package.json b/packages/yarn-plugin/package.json index fd70dc8600..206adeddbe 100644 --- a/packages/yarn-plugin/package.json +++ b/packages/yarn-plugin/package.json @@ -35,6 +35,7 @@ "@yarnpkg/core": "^4.0.3", "@yarnpkg/fslib": "^3.0.2", "chalk": "^4.0.0", + "lodash": "^4.17.21", "semver": "^7.6.0" }, "devDependencies": { diff --git a/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts b/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts index 4cc0c1c9f2..6c7157ebe9 100644 --- a/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts +++ b/packages/yarn-plugin/src/resolver/BackstageResolver.test.ts @@ -16,6 +16,7 @@ import { structUtils } from '@yarnpkg/core'; import { npath, ppath } from '@yarnpkg/fslib'; +import { getManifestByVersion } from '@backstage/release-manifests'; import { BackstageResolver } from './BackstageResolver'; import { createMockDirectory } from '@backstage/backend-test-utils'; @@ -31,6 +32,10 @@ jest.mock('@backstage/release-manifests', () => ({ }), })); +const getManifestByVersionMock = getManifestByVersion as jest.MockedFunction< + typeof getManifestByVersion +>; + describe('BackstageResolver', () => { const mockDir = createMockDirectory(); let backstageResolver: BackstageResolver; @@ -177,5 +182,29 @@ describe('BackstageResolver', () => { ), ).rejects.toThrow(/invalid backstage version/i); }); + + it('memoizes manifest retrieval', async () => { + const descriptor1 = structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:1.23.45', + ); + + for (let i = 0; i < 5; i++) { + await backstageResolver.getCandidates(descriptor1); + } + + expect(getManifestByVersionMock).toHaveBeenCalledTimes(1); + + const descriptor2 = structUtils.makeDescriptor( + structUtils.makeIdent('backstage', 'core'), + 'backstage:6.78.90', + ); + + for (let i = 0; i < 5; i++) { + await backstageResolver.getCandidates(descriptor2); + } + + expect(getManifestByVersionMock).toHaveBeenCalledTimes(2); + }); }); }); diff --git a/packages/yarn-plugin/src/util.ts b/packages/yarn-plugin/src/util.ts index 8431e23cfa..0b613a477c 100644 --- a/packages/yarn-plugin/src/util.ts +++ b/packages/yarn-plugin/src/util.ts @@ -16,11 +16,17 @@ import { ppath, xfs } from '@yarnpkg/fslib'; import { valid as semverValid } from 'semver'; -import { getManifestByVersion } from '@backstage/release-manifests'; +import { memoize } from 'lodash'; +import { getManifestByVersion as getManifestByVersionBase } from '@backstage/release-manifests'; import { BACKSTAGE_JSON, findPaths } from '@backstage/cli-common'; import { Descriptor, structUtils } from '@yarnpkg/core'; import { PROTOCOL } from './constants'; +const getManifestByVersion = memoize( + getManifestByVersionBase, + ({ version }) => version, +); + export const getCurrentBackstageVersion = () => { const workspaceRoot = ppath.resolve(findPaths(ppath.cwd()).targetRoot); diff --git a/yarn.lock b/yarn.lock index ad55a72897..155c0eeb9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -45239,6 +45239,7 @@ __metadata: "@yarnpkg/core": ^4.0.3 "@yarnpkg/fslib": ^3.0.2 chalk: ^4.0.0 + lodash: ^4.17.21 nodemon: ^3.0.1 semver: ^7.6.0 languageName: unknown