Commit 81084565 authored by Sarah Groff Hennigh-Palermo's avatar Sarah Groff Hennigh-Palermo Committed by Jose Ivan Vargas

Improve performance on generating layers view

parent 0463eb5a
......@@ -2,6 +2,7 @@
import { reportToSentry } from '../../utils';
import LinkedGraphWrapper from '../graph_shared/linked_graph_wrapper.vue';
import LinksLayer from '../graph_shared/links_layer.vue';
import { generateColumnsFromLayersListMemoized } from '../parsing_utils';
import { DOWNSTREAM, MAIN, UPSTREAM, ONE_COL_WIDTH, STAGE_VIEW } from './constants';
import LinkedPipelinesColumn from './linked_pipelines_column.vue';
import StageColumnComponent from './stage_column_component.vue';
......@@ -74,7 +75,9 @@ export default {
return this.hasDownstreamPipelines ? this.pipeline.downstream : [];
},
layout() {
return this.isStageView ? this.pipeline.stages : this.generateColumnsFromLayersList();
return this.isStageView
? this.pipeline.stages
: generateColumnsFromLayersListMemoized(this.pipeline, this.pipelineLayers);
},
hasDownstreamPipelines() {
return Boolean(this.pipeline?.downstream?.length > 0);
......@@ -120,26 +123,6 @@ export default {
this.getMeasurements();
},
methods: {
generateColumnsFromLayersList() {
return this.pipelineLayers.map((layers, idx) => {
/*
look up the groups in each layer,
then add each set of layer groups to a stage-like object
*/
const groups = layers.map((id) => {
const { stageIdx, groupIdx } = this.pipeline.stagesLookup[id];
return this.pipeline.stages?.[stageIdx]?.groups?.[groupIdx];
});
return {
name: '',
id: `layer-${idx}`,
status: { action: null },
groups: groups.filter(Boolean),
};
});
},
getMeasurements() {
this.measurements = {
width: this.$refs[this.containerId].scrollWidth,
......
import { uniqWith, isEqual } from 'lodash';
import { isEqual, memoize, uniqWith } from 'lodash';
import { createSankey } from './dag/drawing_utils';
/*
......@@ -170,3 +170,26 @@ export const listByLayers = ({ stages }) => {
return acc;
}, []);
};
export const generateColumnsFromLayersListBare = ({ stages, stagesLookup }, pipelineLayers) => {
return pipelineLayers.map((layers, idx) => {
/*
Look up the groups in each layer,
then add each set of layer groups to a stage-like object.
*/
const groups = layers.map((id) => {
const { stageIdx, groupIdx } = stagesLookup[id];
return stages[stageIdx]?.groups?.[groupIdx];
});
return {
name: '',
id: `layer-${idx}`,
status: { action: null },
groups: groups.filter(Boolean),
};
});
};
export const generateColumnsFromLayersListMemoized = memoize(generateColumnsFromLayersListBare);
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`DAG visualization parsing utilities generateColumnsFromLayersList matches the snapshot 1`] = `
Array [
Object {
"groups": Array [
Object {
"__typename": "CiGroup",
"jobs": Array [
Object {
"__typename": "CiJob",
"name": "build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl",
"needs": Array [],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1482/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1482",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
],
"name": "build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl",
"size": 1,
"stageName": "build",
"status": Object {
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
"jobs": Array [
Object {
"__typename": "CiJob",
"name": "build_b",
"needs": Array [],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1515/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1515",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
],
"name": "build_b",
"size": 1,
"stageName": "build",
"status": Object {
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
"jobs": Array [
Object {
"__typename": "CiJob",
"name": "build_c",
"needs": Array [],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1484/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1484",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
],
"name": "build_c",
"size": 1,
"stageName": "build",
"status": Object {
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
"jobs": Array [
Object {
"__typename": "CiJob",
"name": "build_d 1/3",
"needs": Array [],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1485/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1485",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
Object {
"__typename": "CiJob",
"name": "build_d 2/3",
"needs": Array [],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1486/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1486",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
Object {
"__typename": "CiJob",
"name": "build_d 3/3",
"needs": Array [],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1487/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1487",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
],
"name": "build_d",
"size": 3,
"stageName": "build",
"status": Object {
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
"jobs": Array [
Object {
"__typename": "CiJob",
"name": "test_c",
"needs": Array [],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": null,
"detailsPath": "/root/kinder-pipe/-/pipelines/154",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": null,
},
},
],
"name": "test_c",
"size": 1,
"stageName": "test",
"status": Object {
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
"label": null,
},
},
],
"id": "layer-0",
"name": "",
"status": Object {
"action": null,
},
},
Object {
"groups": Array [
Object {
"__typename": "CiGroup",
"jobs": Array [
Object {
"__typename": "CiJob",
"name": "test_a",
"needs": Array [
"build_c",
"build_b",
"build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl",
],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1514/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1514",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
],
"name": "test_a",
"size": 1,
"stageName": "test",
"status": Object {
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
"jobs": Array [
Object {
"__typename": "CiJob",
"name": "test_b 1/2",
"needs": Array [
"build_d 3/3",
"build_d 2/3",
"build_d 1/3",
"build_b",
"build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl",
],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1489/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1489",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
Object {
"__typename": "CiJob",
"name": "test_b 2/2",
"needs": Array [
"build_d 3/3",
"build_d 2/3",
"build_d 1/3",
"build_b",
"build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl",
],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": Object {
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
"path": "/root/abcd-dag/-/jobs/1490/retry",
"title": "Retry",
},
"detailsPath": "/root/abcd-dag/-/jobs/1490",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": "passed",
},
},
],
"name": "test_b",
"size": 2,
"stageName": "test",
"status": Object {
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
"jobs": Array [
Object {
"__typename": "CiJob",
"name": "test_d",
"needs": Array [
"build_b",
],
"scheduledAt": null,
"status": Object {
"__typename": "DetailedStatus",
"action": null,
"detailsPath": "/root/abcd-dag/-/pipelines/153",
"group": "success",
"hasDetails": true,
"icon": "status_success",
"tooltip": null,
},
},
],
"name": "test_d",
"size": 1,
"stageName": "test",
"status": Object {
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
"label": null,
},
},
],
"id": "layer-1",
"name": "",
"status": Object {
"action": null,
},
},
]
`;
......@@ -3,12 +3,15 @@ import {
createNodeDict,
makeLinksFromNodes,
filterByAncestors,
generateColumnsFromLayersListBare,
listByLayers,
parseData,
removeOrphanNodes,
getMaxNodes,
} from '~/pipelines/components/parsing_utils';
import { mockParsedGraphQLNodes } from './mock_data';
import { mockParsedGraphQLNodes } from './components/dag/mock_data';
import { generateResponse, mockPipelineResponse } from './graph/mock_data';
describe('DAG visualization parsing utilities', () => {
const nodeDict = createNodeDict(mockParsedGraphQLNodes);
......@@ -108,4 +111,45 @@ describe('DAG visualization parsing utilities', () => {
expect(getMaxNodes(layerNodes)).toBe(3);
});
});
describe('generateColumnsFromLayersList', () => {
const pipeline = generateResponse(mockPipelineResponse, 'root/fungi-xoxo');
const layers = listByLayers(pipeline);
const columns = generateColumnsFromLayersListBare(pipeline, layers);
it('returns stage-like objects with default name, id, and status', () => {
columns.forEach((col, idx) => {
expect(col).toMatchObject({
name: '',
status: { action: null },
id: `layer-${idx}`,
});
});
});
it('creates groups that match the list created in listByLayers', () => {
columns.forEach((col, idx) => {
const groupNames = col.groups.map(({ name }) => name);
expect(groupNames).toEqual(layers[idx]);
});
});
it('looks up the correct group object', () => {
columns.forEach((col) => {
col.groups.forEach((group) => {
const groupStage = pipeline.stages.find((el) => el.name === group.stageName);
const groupObject = groupStage.groups.find((el) => el.name === group.name);
expect(group).toBe(groupObject);
});
});
});
/*
Just as a fallback in case multiple functions change, so tests pass
but the implementation moves away from case.
*/
it('matches the snapshot', () => {
expect(columns).toMatchSnapshot();
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment