Skip to content

Commit 4ae7469

Browse files
committed
[DOP-23867] Adjust components to handle new lineage response schemas
1 parent 633209a commit 4ae7469

File tree

4 files changed

+159
-174
lines changed

4 files changed

+159
-174
lines changed

src/components/lineage/nodes/dataset_node/DatasetNode.tsx

Lines changed: 6 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
1-
import { NodeProps, Node, useReactFlow } from "@xyflow/react";
1+
import { NodeProps, Node } from "@xyflow/react";
22
import { useCreatePath, useTranslate } from "react-admin";
33
import { ReactElement, memo } from "react";
44
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
55

6-
import {
7-
DatasetResponseV1,
8-
InputRelationLineageResponseV1,
9-
IORelationSchemaV1,
10-
OutputRelationLineageResponseV1,
11-
} from "@/dataProvider/types";
6+
import { DatasetResponseV1 } from "@/dataProvider/types";
127
import { LocationIconWithType } from "@/components/location";
138
import { Button, CardHeader, Typography } from "@mui/material";
149
import BaseNode from "../base_node/BaseNode";
@@ -18,7 +13,6 @@ export type DatasetNode = Node<DatasetResponseV1, "datasetNode">;
1813

1914
const DatasetNode = (props: NodeProps<DatasetNode>): ReactElement => {
2015
const translate = useTranslate();
21-
const reactFlow = useReactFlow();
2216

2317
let title = props.data.name;
2418
const subheader = `${props.data.location.type}://${props.data.location.name}`;
@@ -33,59 +27,6 @@ const DatasetNode = (props: NodeProps<DatasetNode>): ReactElement => {
3327
id: props.data.id,
3428
});
3529

36-
const outputSchemas = reactFlow
37-
.getEdges()
38-
.filter(
39-
(edge) => edge.data?.kind == "OUTPUT" && edge.target === props.id,
40-
)
41-
// @ts-expect-error Explicit cast
42-
.map((edge) => edge.data as OutputRelationLineageResponseV1)
43-
// sort by last_interaction_at descending
44-
.toSorted((a, b) =>
45-
a.last_interaction_at < b.last_interaction_at ? 1 : -1,
46-
)
47-
.map((output) => output.schema)
48-
.filter((schema) => schema !== null)
49-
// keep unique schemas only
50-
.filter(
51-
(schema, index, array) =>
52-
array.findIndex((item) => item.id == schema.id) == index,
53-
);
54-
55-
const inputSchemas = reactFlow
56-
.getEdges()
57-
.filter(
58-
(edge) => edge.data?.kind == "INPUT" && edge.source === props.id,
59-
)
60-
// @ts-expect-error Explicit cast
61-
.map((edge) => edge.data as InputRelationLineageResponseV1)
62-
// sort by last_interaction_at descending
63-
.toSorted((a, b) =>
64-
a.last_interaction_at < b.last_interaction_at ? 1 : -1,
65-
)
66-
.map((input) => input.schema)
67-
.filter((schema) => schema !== null)
68-
// keep unique schemas only
69-
.filter(
70-
(schema, index, array) =>
71-
array.findIndex((item) => item.id == schema.id) == index,
72-
);
73-
74-
// prefer output schema as there is high chance that it describes all the columns properly.
75-
// read interactions may select only a subset of columns.
76-
let schema: IORelationSchemaV1 | undefined = undefined;
77-
let schemaFrom: string = "input";
78-
let schemaCount = 0;
79-
if (outputSchemas.length > 0) {
80-
schema = outputSchemas.at(0);
81-
schemaFrom = "output";
82-
schemaCount = outputSchemas.length;
83-
} else if (inputSchemas.length > 0) {
84-
schema = inputSchemas.at(0);
85-
schemaFrom = "input";
86-
schemaCount = inputSchemas.length;
87-
}
88-
8930
return (
9031
<BaseNode
9132
nodeId={props.id}
@@ -107,15 +48,15 @@ const DatasetNode = (props: NodeProps<DatasetNode>): ReactElement => {
10748
/>
10849
}
10950
expandableContent={
110-
schema ? (
51+
props.data && props.data.schema ? (
11152
<>
11253
<Typography sx={{ textAlign: "center" }}>
11354
{translate(
114-
`resources.datasets.fields.schema.${schemaFrom}`,
115-
{ smart_count: schemaCount },
55+
`resources.datasets.fields.schema.${props.data.schemaFrom}`,
56+
{ smart_count: props.data.schemaCount },
11657
)}
11758
</Typography>
118-
<DatasetSchemaTable fields={schema.fields} />
59+
<DatasetSchemaTable fields={props.data.schema.fields} />
11960
</>
12061
) : null
12162
}

src/components/lineage/utils/getGraphEdges.tsx

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
import {
2-
LineageRelationResponseV1,
32
OutputRelationLineageResponseV1,
43
SymlinkRelationLineageResponseV1,
54
InputRelationLineageResponseV1,
65
ParentRelationLineageResponseV1,
76
BaseRelationLineageResponseV1,
87
LineageResponseV1,
8+
RelationEndpointLineageResponseV1,
99
} from "@/dataProvider/types";
1010
import { Edge, MarkerType } from "@xyflow/react";
11-
import { getNodeId } from "./getGraphNodes";
1211

1312
const STOKE_THICK = 3;
1413
const STOKE_THIN = 1;
1514

16-
export const getEdgeId = (relation: BaseRelationLineageResponseV1): string => {
15+
const getNodeId = (node: RelationEndpointLineageResponseV1): string => {
16+
return node.kind + "-" + node.id;
17+
};
18+
19+
const getEdgeId = (relation: BaseRelationLineageResponseV1): string => {
1720
// @ts-expect-error Type field may be present in some relation types
1821
const type = relation.type ?? "";
1922
return `${getNodeId(relation.from)}-${type}->${getNodeId(relation.to)}`;
@@ -25,8 +28,6 @@ const getMinimalEdge = (relation: BaseRelationLineageResponseV1): Edge => {
2528
source: getNodeId(relation.from),
2629
target: getNodeId(relation.to),
2730
type: "baseEdge",
28-
// @ts-expect-error For some reason, TS thinks that BaseRelation does not satisfy Record
29-
data: relation,
3031
markerEnd: {
3132
type: MarkerType.ArrowClosed,
3233
},
@@ -40,9 +41,13 @@ const getMinimalEdge = (relation: BaseRelationLineageResponseV1): Edge => {
4041
const getParentEdge = (relation: ParentRelationLineageResponseV1): Edge => {
4142
return {
4243
...getMinimalEdge(relation),
44+
label: "PARENT",
45+
data: {
46+
...relation,
47+
kind: "PARENT",
48+
},
4349
sourceHandle: "bottom",
4450
targetHandle: "top",
45-
label: "PARENT",
4651
};
4752
};
4853

@@ -64,6 +69,10 @@ const getOutputEdge = (relation: OutputRelationLineageResponseV1): Edge => {
6469
return {
6570
...getMinimalEdge(relation),
6671
type: "ioEdge",
72+
data: {
73+
...relation,
74+
kind: "OUTPUT",
75+
},
6776
animated: true,
6877
markerEnd: {
6978
type: MarkerType.ArrowClosed,
@@ -84,6 +93,10 @@ const getInputEdge = (relation: InputRelationLineageResponseV1): Edge => {
8493
return {
8594
...getMinimalEdge(relation),
8695
type: "ioEdge",
96+
data: {
97+
...relation,
98+
kind: "INPUT",
99+
},
87100
animated: true,
88101
markerEnd: {
89102
type: MarkerType.ArrowClosed,
@@ -128,12 +141,17 @@ const getSymlinkEdge = (
128141
// with more simple graphs, like these:
129142
//
130143
// HDFS <-> Hive -> Job
131-
const targetRelations = raw_response.relations.filter(
132-
(r) => r.to.id == relation.to.id || r.from.id == relation.to.id,
144+
const anyTargetInput = raw_response.relations.inputs.find(
145+
(r) => r.from.id == relation.to.id,
133146
);
134-
const targetHasOnlyOutputs = targetRelations.every(
135-
(r) => r.kind == "OUTPUT" || r.kind == "SYMLINK",
147+
const anyTargetOutput = raw_response.relations.outputs.find(
148+
(r) => r.to.id == relation.to.id,
149+
);
150+
const anyTargetSymlink = raw_response.relations.symlinks.find(
151+
(r) => r.to.id == relation.to.id || r.from.id == relation.to.id,
136152
);
153+
const targetHasOnlyOutputs =
154+
(!!anyTargetOutput || !!anyTargetSymlink) && !anyTargetInput;
137155

138156
const color = "purple";
139157

@@ -146,6 +164,10 @@ const getSymlinkEdge = (
146164
target: targetHasOnlyOutputs
147165
? getNodeId(relation.from)
148166
: getNodeId(relation.to),
167+
data: {
168+
...relation,
169+
kind: "SYMLINK",
170+
},
149171
markerStart: {
150172
type: MarkerType.ArrowClosed,
151173
color: color,
@@ -164,35 +186,15 @@ const getSymlinkEdge = (
164186
};
165187
};
166188

167-
const getGraphEdge = (
168-
relation: LineageRelationResponseV1,
169-
raw_response: LineageResponseV1,
170-
): Edge | null => {
171-
switch (relation.kind) {
172-
case "PARENT":
173-
return getParentEdge(relation);
174-
case "OUTPUT":
175-
return getOutputEdge(relation);
176-
case "INPUT":
177-
return getInputEdge(relation);
178-
case "SYMLINK":
179-
return getSymlinkEdge(relation, raw_response);
180-
default:
181-
return getMinimalEdge(relation);
182-
}
183-
};
184-
185189
const getGraphEdges = (raw_response: LineageResponseV1): Edge[] => {
186-
const result: Edge[] = [];
187-
188-
raw_response.relations.forEach((relation) => {
189-
const edge = getGraphEdge(relation, raw_response);
190-
if (edge) {
191-
result.push(edge);
192-
}
193-
});
194-
195-
return result;
190+
return [
191+
...raw_response.relations.parents.map(getParentEdge),
192+
...raw_response.relations.inputs.map(getInputEdge),
193+
...raw_response.relations.outputs.map(getOutputEdge),
194+
...raw_response.relations.symlinks
195+
.map((relation) => getSymlinkEdge(relation, raw_response))
196+
.filter((edge) => edge !== null),
197+
];
196198
};
197199

198200
export default getGraphEdges;

0 commit comments

Comments
 (0)