Implementation:Risingwavelabs Risingwave RelationGraph Component
| Property | Value |
|---|---|
| Component | RelationGraph |
| Source File | dashboard/components/RelationGraph.tsx
|
| Language | TypeScript / TSX |
| Lines | 443 |
| Category | Dashboard UI Component |
| Framework | React, D3.js, dagre |
Overview
The RelationGraph component renders an interactive SVG graph showing dependency relationships between database relations (tables, materialized views, sinks, sources, etc.) in the RisingWave dashboard. It uses dagre for left-to-right directed graph layout and D3 for SVG rendering with the enter/update/exit pattern.
Each relation node is rendered as a rounded rectangle containing a colored type-icon circle (M for materialized view, T for table, K for sink, S for source) and the relation name. Edges between relations are colored and sized based on backpressure rates from channel statistics. Node icon fill colors reflect epoch latency from relation statistics. Tooltips appear on edge hover showing backpressure and throughput data, and clicking a node opens a CatalogModal with detailed catalog information.
Code Reference
Source Location
dashboard/components/RelationGraph.tsx
Full URL: dashboard/components/RelationGraph.tsx
Signature
export default function RelationGraph({
nodes,
selectedId,
setSelectedId,
channelStats,
relationStats,
}: {
nodes: RelationPoint[]
selectedId: string | undefined
setSelectedId: (id: string) => void
channelStats?: Map<string, ChannelDeltaStats>
relationStats: { [relationId: number]: RelationStats } | undefined
}): JSX.Element
Imports
import { theme } from "@chakra-ui/react"
import * as d3 from "d3"
import * as dagre from "dagre"
import { useCallback, useEffect, useRef } from "react"
import {
Relation, relationIsStreamingJob, relationType, relationTypeTitleCase,
} from "../lib/api/streaming"
import {
Edge, Enter, Position, RelationPoint, RelationPointPosition,
} from "../lib/layout"
import { ChannelDeltaStats, RelationStats } from "../proto/gen/monitor_service"
import { CatalogModal, useCatalogModal } from "./CatalogModal"
import {
backPressureColor, backPressureWidth, epochToUnixMillis, latencyToColor,
} from "./utils/backPressure"
I/O Contract
Inputs
| Parameter | Type | Required | Description |
|---|---|---|---|
nodes |
RelationPoint[] |
Yes | Array of relation nodes with their parent dependency IDs |
selectedId |
undefined | Yes | Currently selected relation ID for visual highlighting |
setSelectedId |
(id: string) => void |
Yes | Callback to update the selected relation ID when a node is clicked |
channelStats |
Map<string, ChannelDeltaStats> |
No | Backpressure and throughput statistics for channels between relations, keyed by "sourceId_targetId"
|
relationStats |
undefined | No | Per-relation stats including current epoch for latency-based icon coloring |
Outputs
The component renders:
- An SVG element with zoom/pan support via
d3.zoom - Relation nodes -- rounded rectangles with a colored type-icon circle and relation name text
- Dependency edges -- curved paths (using
d3.curveBasis) colored and sized by backpressure rate - Tooltips -- on edge hover, showing backpressure percentage and send/receive throughput
- CatalogModal -- opened on node click to display full catalog details for the relation
Exported Constants
export const boxWidth = 150 // Width of each relation box in pixels
export const boxHeight = 45 // Height of each relation box in pixels
Layout Configuration
const iconRadius = 12 // Radius of the icon circle in pixels
const layerMargin = 80 // Horizontal spacing between layers in the graph
const rowMargin = 30 // Vertical spacing between rows in the graph
const layoutMargin = 30 // Margin around the entire graph layout
The dagre graph is configured with rankdir: "LR" (left-to-right), using rowMargin as node separation and layerMargin as rank separation.
Internal Helpers
boundBox
function boundBox(relationPosition: RelationPointPosition[]): {
width: number
height: number
}
Calculates the overall bounding box dimensions for all positioned relation nodes by finding the maximum x + boxWidth and y + boxHeight across all positions.
Usage Examples
Typical usage from the Relation Graph page
import RelationGraph from "../components/RelationGraph"
<RelationGraph
nodes={relationPoints}
selectedId={selectedRelationId}
setSelectedId={setSelectedRelationId}
channelStats={channelStatsMap}
relationStats={relationStatsMap}
/>Related Pages
- Risingwavelabs_Risingwave_FragmentGraph_Component -- Sibling graph component for fragment-level plan node visualization
- Risingwavelabs_Risingwave_Relations_Component -- Table-based relation list component
- Risingwavelabs_Risingwave_Dashboard_Streaming_API -- API layer providing relation and streaming data