Skip to content

Commit

Permalink
feat(dep-graph): launch path tracing (#9919)
Browse files Browse the repository at this point in the history
  • Loading branch information
philipjfulcher authored Apr 21, 2022
1 parent 5f12ce0 commit 3dc818f
Show file tree
Hide file tree
Showing 14 changed files with 229 additions and 67 deletions.
11 changes: 6 additions & 5 deletions dep-graph/client-e2e/src/integration/app.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
getCheckedProjectItems,
getDeselectAllButton,
getFocusButtonForProject,
getGroupByFolderCheckbox,
getImageDownloadButton,
getIncludeProjectsInPathButton,
Expand Down Expand Up @@ -146,15 +147,15 @@ describe('dep-graph-client', () => {
describe('focusing projects in sidebar', () => {
it('should select appropriate projects', () => {
cy.contains('nx-dev').scrollIntoView().should('be.visible');
cy.get('[data-project="nx-dev"]').prev('button').click({ force: true });
getFocusButtonForProject('nx-dev').click({ force: true });

getCheckedProjectItems().should('have.length', 11);
});
});

describe('unfocus button', () => {
it('should uncheck all project items', () => {
cy.get('[data-project="nx-dev"]').prev('button').click({ force: true });
getFocusButtonForProject('nx-dev').click({ force: true });
getUnfocusProjectButton().click();

getUncheckedProjectItems().should('have.length', 62);
Expand Down Expand Up @@ -182,12 +183,12 @@ describe('dep-graph-client', () => {
});

it('should be shown when a project is selected', () => {
cy.get('[data-project="nx-dev"]').prev('button').click({ force: true });
cy.get('[data-project="nx-dev"]').click({ force: true });
getImageDownloadButton().should('not.have.class', 'opacity-0');
});

it('should be hidden when no more projects are selected', () => {
cy.get('[data-project="nx-dev"]').prev('button').click({ force: true });
cy.get('[data-project="nx-dev"]').click({ force: true });
getDeselectAllButton().click();
getImageDownloadButton().should('have.class', 'opacity-0');
});
Expand All @@ -196,7 +197,7 @@ describe('dep-graph-client', () => {
describe('setting url params', () => {
it('should set focused project', () => {
cy.contains('nx-dev').scrollIntoView().should('be.visible');
cy.get('[data-project="nx-dev"]').prev('button').click({ force: true });
getFocusButtonForProject('nx-dev').click({ force: true });

cy.url().should('contain', 'focus=nx-dev');
});
Expand Down
3 changes: 3 additions & 0 deletions dep-graph/client-e2e/src/support/app.po.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ export const getIncludeProjectsInPathButton = () =>

export const getImageDownloadButton = () =>
cy.get('[data-cy=downloadImageButton]');

export const getFocusButtonForProject = (projectName: string) =>
cy.get(`[data-cy="focus-button-${projectName}"]`);
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ describe('dep-graph-client in watch mode', () => {
// TODO: This test is getting flaky but was fixed by increasing the tick time between checks
// Figure out a better way to test this
it('should retain selected projects as new libs are created', () => {
cy.contains('existing-app-1').siblings('button').click();
cy.contains('existing-lib-1').siblings('button').click();
cy.get('[data-project="existing-app-1"]').click();
cy.get('[data-project="existing-lib-1"]').click();

cy.tick(6000);

Expand Down
12 changes: 12 additions & 0 deletions dep-graph/client/src/app/machines/dep-graph.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const initialContext: DepGraphContext = {
tracing: {
start: null,
end: null,
algorithm: 'shortest',
},
};

Expand Down Expand Up @@ -211,6 +212,15 @@ export const depGraphMachine = Machine<
setSearchDepth: {
actions: ['setSearchDepth', 'notifyRouteSearchDepth'],
},
setTracingAlgorithm: {
actions: [
assign((ctx, event) => {
ctx.tracing.algorithm = event.algorithm;
}),
'notifyRouteTracing',
'notifyGraphTracing',
],
},
filterByText: {
target: 'textFiltered',
},
Expand Down Expand Up @@ -280,6 +290,7 @@ export const depGraphMachine = Machine<
type: 'notifyGraphTracing',
start: ctx.tracing.start,
end: ctx.tracing.end,
algorithm: ctx.tracing.algorithm,
};
},
{
Expand Down Expand Up @@ -385,6 +396,7 @@ export const depGraphMachine = Machine<
type: 'notifyRouteTracing',
start: ctx.tracing.start,
end: ctx.tracing.end,
algorithm: ctx.tracing.algorithm,
};
},
{
Expand Down
21 changes: 8 additions & 13 deletions dep-graph/client/src/app/machines/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,11 @@ export class GraphService {

case 'notifyGraphTracing':
if (event.start && event.end) {
this.traceProjects(event.start, event.end);
// this.traceAllProjects(event.start, event.end);
if (event.algorithm === 'shortest') {
this.traceProjects(event.start, event.end);
} else {
this.traceAllProjects(event.start, event.end);
}
}
break;
}
Expand Down Expand Up @@ -390,13 +393,6 @@ export class GraphService {
if (iterations >= 1000) {
console.log('failsafe triggered!');
}
paths.forEach((currentPath) => {
console.log(
currentPath
.map((path) => path.map((element) => element.id()))
.join(' => ')
);
});

let finalCollection = this.traversalGraph.collection();

Expand All @@ -413,11 +409,10 @@ export class GraphService {
}
});

console.log(finalCollection.length);

finalCollection.union(finalCollection.ancestors());
console.log(finalCollection.map((element) => element.id()));
this.transferToRenderGraph(finalCollection);
this.transferToRenderGraph(
finalCollection.union(finalCollection.ancestors())
);
}

private transferToRenderGraph(elements: cy.Collection) {
Expand Down
12 changes: 11 additions & 1 deletion dep-graph/client/src/app/machines/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface GraphPerfReport {
numNodes: number;
numEdges: number;
}

export type TracingAlgorithmType = 'shortest' | 'all';
// The events that the machine handles

export type DepGraphUIEvents =
Expand All @@ -40,6 +42,7 @@ export type DepGraphUIEvents =
| { type: 'setTracingEnd'; projectName: string }
| { type: 'clearTraceStart' }
| { type: 'clearTraceEnd' }
| { type: 'setTracingAlgorithm'; algorithm: TracingAlgorithmType }
| { type: 'setCollapseEdges'; collapseEdges: boolean }
| { type: 'setIncludeProjectsByPath'; includeProjectsByPath: boolean }
| { type: 'incrementSearchDepth' }
Expand Down Expand Up @@ -126,6 +129,7 @@ export type GraphRenderEvents =
type: 'notifyGraphTracing';
start: string;
end: string;
algorithm: TracingAlgorithmType;
};

export type RouteEvents =
Expand Down Expand Up @@ -156,7 +160,12 @@ export type RouteEvents =
type: 'notifyRouteSelectAffected';
}
| { type: 'notifyRouteClearSelect' }
| { type: 'notifyRouteTracing'; start: string; end: string };
| {
type: 'notifyRouteTracing';
start: string;
end: string;
algorithm: TracingAlgorithmType;
};

export type AllEvents = DepGraphUIEvents | GraphRenderEvents | RouteEvents;

Expand Down Expand Up @@ -184,6 +193,7 @@ export interface DepGraphContext {
tracing: {
start: string;
end: string;
algorithm: TracingAlgorithmType;
};
}

Expand Down
6 changes: 6 additions & 0 deletions dep-graph/client/src/app/machines/route-listener.actor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ function parseSearchParamsToEvents(searchParams: string): DepGraphUIEvents[] {
});
}
break;
case 'traceAlgorithm':
if (value === 'shortest' || value === 'all') {
// this needs to go before other tracing options or else the default of 'shortest' gets used
events.unshift({ type: 'setTracingAlgorithm', algorithm: value });
}
break;
case 'traceStart':
events.push({
type: 'setTracingStart',
Expand Down
9 changes: 7 additions & 2 deletions dep-graph/client/src/app/machines/route-setter.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ type ParamKeys =
| 'select'
| 'collapseEdges'
| 'traceStart'
| 'traceEnd';
| 'traceEnd'
| 'traceAlgorithm';
type ParamRecord = Record<ParamKeys, string | null>;

function reduceParamRecordToQueryString(params: ParamRecord): string {
Expand All @@ -37,6 +38,7 @@ export const createRouteMachine = () => {
select: params.get('select'),
traceStart: params.get('traceStart'),
traceEnd: params.get('traceEnd'),
traceAlgorithm: params.get('traceAlgorithm'),
};

const initialContext = {
Expand All @@ -61,6 +63,7 @@ export const createRouteMachine = () => {
collapseEdges: null,
traceStart: null,
traceEnd: null,
traceAlgorithm: null,
},
},
always: {
Expand Down Expand Up @@ -129,15 +132,17 @@ export const createRouteMachine = () => {
},
notifyRouteTracing: {
actions: assign((ctx, event) => {
if (event.start !== null && event.end !== null) {
if (event.start !== null && event.end !== null && event.algorithm) {
ctx.params.traceStart = event.start;
ctx.params.traceEnd = event.end;
ctx.params.traceAlgorithm = event.algorithm;

ctx.params.focus = null;
ctx.params.select = null;
} else {
ctx.params.traceStart = null;
ctx.params.traceEnd = null;
ctx.params.traceAlgorithm = null;
}
}),
},
Expand Down
3 changes: 2 additions & 1 deletion dep-graph/client/src/app/machines/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { ProjectGraphProjectNode } from '@nrwl/devkit';
import { DepGraphSelector } from '../hooks/use-dep-graph-selector';
import { WorkspaceLayout } from '../interfaces';
import { GraphPerfReport } from './interfaces';
import { GraphPerfReport, TracingAlgorithmType } from './interfaces';

export const allProjectsSelector: DepGraphSelector<
ProjectGraphProjectNode[]
Expand Down Expand Up @@ -52,4 +52,5 @@ export const hasAffectedProjectsSelector: DepGraphSelector<boolean> = (state) =>
export const getTracingInfo: DepGraphSelector<{
start: string;
end: string;
algorithm: TracingAlgorithmType;
}> = (state) => state.context.tracing;
9 changes: 9 additions & 0 deletions dep-graph/client/src/app/machines/tracing.state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ export const tracingStateConfig: DepGraphStateNodeConfig = {
'notifyRouteTracing',
'notifyGraphTracing',
],
exit: [
assign((ctx, event) => {
if (event.type !== 'setTracingStart' && event.type !== 'setTracingEnd') {
ctx.tracing.start = null;
ctx.tracing.end = null;
}
}),
'notifyRouteTracing',
],
on: {
clearTraceStart: {
actions: [
Expand Down
63 changes: 30 additions & 33 deletions dep-graph/client/src/app/project-node-tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import ExperimentalFeature from './experimental-feature';
import { getDepGraphService } from './machines/dep-graph.service';

export interface ProjectNodeToolTipProps {
Expand Down Expand Up @@ -53,38 +52,36 @@ function ProjectNodeToolTip({ type, id, tags }: ProjectNodeToolTipProps) {
<div className="flex">
<button onClick={onFocus}>Focus</button>
<button onClick={onExclude}>Exclude</button>
<ExperimentalFeature>
<button className="flex flex-row items-center" onClick={onStartTrace}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="mr-2 h-5 w-5 text-slate-500"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z"
clipRule="evenodd"
/>
</svg>
Start
</button>
<button className="flex flex-row items-center" onClick={onEndTrace}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="mr-2 h-5 w-5 text-slate-500"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M3 6a3 3 0 013-3h10a1 1 0 01.8 1.6L14.25 8l2.55 3.4A1 1 0 0116 13H6a1 1 0 00-1 1v3a1 1 0 11-2 0V6z"
clipRule="evenodd"
/>
</svg>
End
</button>
</ExperimentalFeature>
<button className="flex flex-row items-center" onClick={onStartTrace}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="mr-2 h-5 w-5 text-slate-500"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z"
clipRule="evenodd"
/>
</svg>
Start
</button>
<button className="flex flex-row items-center" onClick={onEndTrace}>
<svg
xmlns="http://www.w3.org/2000/svg"
className="mr-2 h-5 w-5 text-slate-500"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M3 6a3 3 0 013-3h10a1 1 0 01.8 1.6L14.25 8l2.55 3.4A1 1 0 0116 13H6a1 1 0 00-1 1v3a1 1 0 11-2 0V6z"
clipRule="evenodd"
/>
</svg>
End
</button>
</div>
</div>
);
Expand Down
Loading

0 comments on commit 3dc818f

Please sign in to comment.