mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
## What kind of change does this PR introduce? Feature. Stack 4 of 5 for [PIPE-1007](https://linear.app/supabase/issue/PIPE-1007/move-read-replicas-out-of-replication-into-infrastructure). Contributes to PIPE-1008. ## What is the current behavior? Database / Replication lists, creates, and diagrams read replicas alongside pipelines. ## What is the new behavior? Replication is pipelines-only. No replica rows, type, or diagram nodes. `?destinationType=Read+Replica` redirects to Infrastructure. A short callout points create-mode users at the new home. ## Additional context Please review, but do not merge until [#48921](https://github.com/supabase/supabase/pull/48921) is ready to follow immediately. The flag is already on, so this PR is the user-facing cutover off Replication. ## To test `infrastructure:read_replicas` is an enabled-feature, on by default. There is no Feature Preview or ConfigCat switch. You should already see the Infrastructure Read replicas section. If you do not, your profile lists `infrastructure:read_replicas` in `disabled_features`. Open [Database / Replication](https://studio-staging-git-danny-pipe-1007-04-cut-from-77ef95-supabase.vercel.app/dashboard/project/_/database/replication?destinationType=Read+Replica). You should land on Infrastructure with the add-replica sheet, not a replica destination type. The Replication page itself should be pipelines-only. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added guidance directing users to Infrastructure to create read replicas. * Added automatic redirection for legacy read-replica links. * **Updates** * Replication destinations now focus exclusively on external analytics and pipeline destinations. * Updated destination selection, empty states, descriptions, and diagrams to reflect the streamlined experience. * Removed read replicas from the replication destination list and related creation flow. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Jeremias Menichelli <jmenichelli@gmail.com>
118 lines
3.6 KiB
TypeScript
118 lines
3.6 KiB
TypeScript
import { Background, ColorMode, ReactFlow, ReactFlowProvider, useReactFlow } from '@xyflow/react'
|
|
import { useParams } from 'common'
|
|
import { useTheme } from 'next-themes'
|
|
import { useEffect, useMemo } from 'react'
|
|
|
|
import { PrimaryDatabaseNode, ReplicationNode } from './Nodes'
|
|
import { getDagreGraphLayout } from './ReplicationDiagram.utils'
|
|
import { useReplicationDestinationsQuery } from '@/data/replication/destinations-query'
|
|
import { timeout } from '@/lib/helpers'
|
|
|
|
import '@xyflow/react/dist/style.css'
|
|
|
|
import { SmoothstepEdge } from './Edges'
|
|
import { checkLocalETLNotSetUp } from '@/data/replication/utils'
|
|
|
|
export const ReplicationDiagram = () => {
|
|
return (
|
|
<ReactFlowProvider>
|
|
<ReplicationDiagramContent />
|
|
</ReactFlowProvider>
|
|
)
|
|
}
|
|
|
|
const nodeTypes = {
|
|
primary: PrimaryDatabaseNode,
|
|
replication: ReplicationNode,
|
|
}
|
|
|
|
const edgeTypes = { smoothstep: SmoothstepEdge }
|
|
|
|
const ReplicationDiagramContent = () => {
|
|
const reactFlow = useReactFlow()
|
|
const { resolvedTheme } = useTheme()
|
|
const { ref: projectRef = 'default' } = useParams()
|
|
|
|
const {
|
|
data,
|
|
error: destinationsError,
|
|
isSuccess: isSuccessDestinations,
|
|
isError: isErrorDestinations,
|
|
} = useReplicationDestinationsQuery({
|
|
projectRef,
|
|
})
|
|
const destinations = useMemo(() => data?.destinations ?? [], [data])
|
|
const isLocalETLNotSetUp = checkLocalETLNotSetUp(destinationsError)
|
|
const skipRenderingDestinations = isErrorDestinations && isLocalETLNotSetUp
|
|
|
|
const nodes = useMemo(() => {
|
|
return [
|
|
{ id: projectRef, type: 'primary', data: {}, position: { x: 0, y: 5 } },
|
|
...destinations.map((x) => ({
|
|
id: x.id.toString(),
|
|
type: 'replication',
|
|
data: {},
|
|
position: { x: 0, y: 0 },
|
|
})),
|
|
]
|
|
}, [destinations, projectRef])
|
|
|
|
const edges = useMemo(() => {
|
|
const shiftEdgeEnd = destinations.length > 1
|
|
|
|
return destinations.map((x) => ({
|
|
id: `${projectRef}-${x.id}`,
|
|
source: projectRef,
|
|
target: x.id.toString(),
|
|
type: 'smoothstep',
|
|
className: 'cursor-default!',
|
|
data: { type: 'etl', identifier: x.id.toString(), shiftEdgeEnd },
|
|
}))
|
|
}, [destinations, projectRef])
|
|
|
|
const backgroundPatternColor =
|
|
resolvedTheme === 'dark' ? 'rgba(255, 255, 255, 0.3)' : 'rgba(0, 0, 0, 0.4)'
|
|
|
|
const setReactFlow = async () => {
|
|
const graph = getDagreGraphLayout(nodes, edges)
|
|
reactFlow.setNodes(graph.nodes)
|
|
reactFlow.setEdges(graph.edges)
|
|
|
|
// [Joshen] Odd fix to ensure that react flow snaps back to center when adding nodes
|
|
await timeout(1)
|
|
reactFlow.fitView({ minZoom: 0.8, maxZoom: 0.9 })
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (nodes.length > 0 && (isSuccessDestinations || skipRenderingDestinations)) {
|
|
setReactFlow()
|
|
}
|
|
}, [nodes, isSuccessDestinations, skipRenderingDestinations])
|
|
|
|
return (
|
|
<div className="nowheel relative h-[350px] w-full border border-muted rounded-md overflow-hidden">
|
|
<ReactFlow
|
|
// FIXME: https://github.com/xyflow/xyflow/issues/4876
|
|
colorMode={'' as unknown as ColorMode}
|
|
fitView
|
|
fitViewOptions={{ minZoom: 0.8, maxZoom: 0.9 }}
|
|
className="bg"
|
|
zoomOnPinch={false}
|
|
zoomOnScroll={false}
|
|
nodesDraggable={false}
|
|
nodesConnectable={false}
|
|
zoomOnDoubleClick={false}
|
|
edgesFocusable={false}
|
|
edgesReconnectable={false}
|
|
defaultNodes={[]}
|
|
defaultEdges={[]}
|
|
nodeTypes={nodeTypes}
|
|
edgeTypes={edgeTypes}
|
|
proOptions={{ hideAttribution: true }}
|
|
>
|
|
<Background color={backgroundPatternColor} />
|
|
</ReactFlow>
|
|
</div>
|
|
)
|
|
}
|