Skip to content

Commit

Permalink
fix(misc): various inference plugins caching should track changes (#2…
Browse files Browse the repository at this point in the history
…3315)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

## Current Behavior
Plugin's cache entries overwrite each other if multiple instances of the
same plugin are running. They also don't remember previous cache states.

## Expected Behavior
Plugin's caches grow as changes are made, and don't overwrite previous
entries.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
  • Loading branch information
AgentEnder committed May 23, 2024
1 parent 445916f commit a4a185f
Show file tree
Hide file tree
Showing 21 changed files with 389 additions and 422 deletions.
4 changes: 4 additions & 0 deletions packages/cypress/src/plugins/plugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,10 @@ describe('@nx/cypress/plugin', () => {
});

function mockCypressConfig(cypressConfig: Cypress.ConfigOptions) {
// This isn't JS, but all that really matters here
// is that the hash is different after updating the
// config file. The actual config read is mocked below.
tempFs.createFileSync('cypress.config.js', JSON.stringify(cypressConfig));
jest.mock(
join(tempFs.tempDir, 'cypress.config.js'),
() => ({
Expand Down
33 changes: 16 additions & 17 deletions packages/cypress/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,22 @@ export interface CypressPluginOptions {
}

const cachePath = join(projectGraphCacheDirectory, 'cypress.hash');
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};

const calculatedTargets: Record<string, CypressTargets> = {};
const targetsCache = readTargetsCache();

function readTargetsCache(): Record<string, CypressTargets> {
return readJsonFile(cachePath);
return existsSync(cachePath) ? readJsonFile(cachePath) : {};
}

function writeTargetsToCache(targets: Record<string, CypressTargets>) {
writeJsonFile(cachePath, targets);
function writeTargetsToCache() {
const oldCache = readTargetsCache();
writeJsonFile(cachePath, {
...oldCache,
targetsCache,
});
}

export const createDependencies: CreateDependencies = () => {
writeTargetsToCache(calculatedTargets);
writeTargetsToCache();
return [];
};

Expand All @@ -67,16 +69,13 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
getLockFileName(detectPackageManager(context.workspaceRoot)),
]);

const { targets, metadata } = targetsCache[hash]
? targetsCache[hash]
: await buildCypressTargets(
configFilePath,
projectRoot,
options,
context
);

calculatedTargets[hash] = { targets, metadata };
targetsCache[hash] ??= await buildCypressTargets(
configFilePath,
projectRoot,
options,
context
);
const { targets, metadata } = targetsCache[hash];

const project: Omit<ProjectConfiguration, 'root'> = {
projectType: 'application',
Expand Down
28 changes: 7 additions & 21 deletions packages/detox/src/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,31 +22,21 @@ export interface DetoxPluginOptions {
}

const cachePath = join(projectGraphCacheDirectory, 'detox.hash');
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};

const calculatedTargets: Record<
string,
Record<string, TargetConfiguration>
> = {};
const targetsCache = readTargetsCache();

function readTargetsCache(): Record<
string,
Record<string, TargetConfiguration<DetoxPluginOptions>>
> {
return readJsonFile(cachePath);
return existsSync(cachePath) ? readJsonFile(cachePath) : {};
}

function writeTargetsToCache(
targets: Record<
string,
Record<string, TargetConfiguration<DetoxPluginOptions>>
>
) {
writeJsonFile(cachePath, targets);
function writeTargetsToCache() {
writeJsonFile(cachePath, targetsCache);
}

export const createDependencies: CreateDependencies = () => {
writeTargetsToCache(calculatedTargets);
writeTargetsToCache();
return [];
};

Expand All @@ -66,16 +56,12 @@ export const createNodes: CreateNodes<DetoxPluginOptions> = [
getLockFileName(detectPackageManager(context.workspaceRoot)),
]);

const targets = targetsCache[hash]
? targetsCache[hash]
: buildDetoxTargets(projectRoot, options, context);

calculatedTargets[hash] = targets;
targetsCache[hash] ??= buildDetoxTargets(projectRoot, options, context);

return {
projects: {
[projectRoot]: {
targets,
targets: targetsCache[hash],
},
},
};
Expand Down
32 changes: 11 additions & 21 deletions packages/expo/plugins/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,31 +30,25 @@ export interface ExpoPluginOptions {
}

const cachePath = join(projectGraphCacheDirectory, 'expo.hash');
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};

const calculatedTargets: Record<
string,
Record<string, TargetConfiguration>
> = {};
const targetsCache = readTargetsCache();

function readTargetsCache(): Record<
string,
Record<string, TargetConfiguration<ExpoPluginOptions>>
> {
return readJsonFile(cachePath);
return existsSync(cachePath) ? readJsonFile(cachePath) : {};
}

function writeTargetsToCache(
targets: Record<
string,
Record<string, TargetConfiguration<ExpoPluginOptions>>
>
) {
writeJsonFile(cachePath, targets);
function writeTargetsToCache() {
const oldCache = readTargetsCache();
writeJsonFile(cachePath, {
...oldCache,
targetsCache,
});
}

export const createDependencies: CreateDependencies = () => {
writeTargetsToCache(calculatedTargets);
writeTargetsToCache();
return [];
};

Expand Down Expand Up @@ -82,16 +76,12 @@ export const createNodes: CreateNodes<ExpoPluginOptions> = [
getLockFileName(detectPackageManager(context.workspaceRoot)),
]);

const targets = targetsCache[hash]
? targetsCache[hash]
: buildExpoTargets(projectRoot, options, context);

calculatedTargets[hash] = targets;
targetsCache[hash] ??= buildExpoTargets(projectRoot, options, context);

return {
projects: {
[projectRoot]: {
targets,
targets: targetsCache[hash],
},
},
};
Expand Down
4 changes: 2 additions & 2 deletions packages/gradle/src/plugin/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
getGradleReport,
invalidateGradleReportCache,
} from '../utils/get-gradle-report';
import { calculatedTargets, writeTargetsToCache } from './nodes';
import { writeTargetsToCache } from './nodes';

export const createDependencies: CreateDependencies = async (
_,
Expand Down Expand Up @@ -58,7 +58,7 @@ export const createDependencies: CreateDependencies = async (
gradleDependenciesEnd.name
);

writeTargetsToCache(calculatedTargets);
writeTargetsToCache();
if (dependencies.length) {
invalidateGradleReportCache();
}
Expand Down
173 changes: 84 additions & 89 deletions packages/gradle/src/plugin/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,39 +34,26 @@ export interface GradlePluginOptions {
}

const cachePath = join(projectGraphCacheDirectory, 'gradle.hash');
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};

export const calculatedTargets: Record<
const targetsCache = readTargetsCache();
type GradleTargets = Record<
string,
{
name: string;
targets: Record<string, TargetConfiguration>;
metadata: ProjectConfiguration['metadata'];
}
> = {};
>;

function readTargetsCache(): Record<
string,
{
name: string;
targets: Record<string, TargetConfiguration>;
metadata: ProjectConfiguration['metadata'];
}
> {
return readJsonFile(cachePath);
function readTargetsCache(): GradleTargets {
return existsSync(cachePath) ? readJsonFile(cachePath) : {};
}

export function writeTargetsToCache(
targets: Record<
string,
{
name: string;
targets: Record<string, TargetConfiguration>;
metadata: ProjectConfiguration['metadata'];
}
>
) {
writeJsonFile(cachePath, targets);
export function writeTargetsToCache() {
const oldCache = readTargetsCache();
writeJsonFile(cachePath, {
...oldCache,
...targetsCache,
});
}

export const createNodes: CreateNodes<GradlePluginOptions> = [
Expand All @@ -83,76 +70,84 @@ export const createNodes: CreateNodes<GradlePluginOptions> = [
options ?? {},
context
);
if (targetsCache[hash]) {
calculatedTargets[hash] = targetsCache[hash];
return {
projects: {
[projectRoot]: targetsCache[hash],
},
};
}

try {
const {
gradleProjectToTasksTypeMap,
gradleFileToOutputDirsMap,
gradleFileToGradleProjectMap,
gradleProjectToProjectName,
} = getGradleReport();

const gradleProject = gradleFileToGradleProjectMap.get(
gradleFilePath
) as string;
const projectName = gradleProjectToProjectName.get(gradleProject);
if (!projectName) {
return;
}

const tasksTypeMap = gradleProjectToTasksTypeMap.get(
gradleProject
) as Map<string, string>;
let tasks: GradleTask[] = [];
for (let [taskName, taskType] of tasksTypeMap.entries()) {
tasks.push({
type: taskType,
name: taskName,
});
}

const outputDirs = gradleFileToOutputDirsMap.get(gradleFilePath) as Map<
string,
string
>;

const { targets, targetGroups } = createGradleTargets(
tasks,
options,
context,
outputDirs,
gradleProject
);
const project = {
name: projectName,
targets,
metadata: {
targetGroups,
technologies: ['gradle'],
},
};
calculatedTargets[hash] = project;

return {
projects: {
[projectRoot]: project,
},
};
} catch (e) {
console.error(e);
targetsCache[hash] ??= createGradleProject(
gradleFilePath,
options,
context
);
const project = targetsCache[hash];
if (!project) {
return {};
}
return {
projects: {
[projectRoot]: project,
},
};
},
];

function createGradleProject(
gradleFilePath: string,
options: GradlePluginOptions | undefined,
context: CreateNodesContext
) {
try {
const {
gradleProjectToTasksTypeMap,
gradleFileToOutputDirsMap,
gradleFileToGradleProjectMap,
gradleProjectToProjectName,
} = getGradleReport();

const gradleProject = gradleFileToGradleProjectMap.get(
gradleFilePath
) as string;
const projectName = gradleProjectToProjectName.get(gradleProject);
if (!projectName) {
return;
}

const tasksTypeMap = gradleProjectToTasksTypeMap.get(gradleProject) as Map<
string,
string
>;
let tasks: GradleTask[] = [];
for (let [taskName, taskType] of tasksTypeMap.entries()) {
tasks.push({
type: taskType,
name: taskName,
});
}

const outputDirs = gradleFileToOutputDirsMap.get(gradleFilePath) as Map<
string,
string
>;

const { targets, targetGroups } = createGradleTargets(
tasks,
options,
context,
outputDirs,
gradleProject
);
const project = {
name: projectName,
targets,
metadata: {
targetGroups,
technologies: ['gradle'],
},
};

return project;
} catch (e) {
console.error(e);
return undefined;
}
}

function createGradleTargets(
tasks: GradleTask[],
options: GradlePluginOptions | undefined,
Expand Down

0 comments on commit a4a185f

Please sign in to comment.