mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 01:45:10 +03:00
## What kind of change does this PR introduce? Feature and docs update. ## What is the current behavior? The Dashboard lists Pipelines destinations under Database > Replication. Read replicas have moved to Infrastructure, but the temporary notices remain on the destinations page and new destination sheet. Closes PIPE-1021. ## What is the new behavior? The canonical Dashboard routes are Database > Pipelines, while legacy Replication list and detail URLs permanently redirect to the equivalent Pipelines routes. Navigation, command palette, shortcuts, pipeline links, docs, and current marketing copy use Pipelines. Read-replica notices and their obsolete dismissal state are removed. | Before | After | | --- | --- | | <img width="1024" height="759" alt="Replication Database Agua Basket Supabase" src="https://github.com/user-attachments/assets/53f9f565-1ed1-43e9-a7d9-b66b2a47e948" /> | <img width="1024" height="759" alt="2540" src="https://github.com/user-attachments/assets/14ab2d61-d01c-483f-9d4f-0ac286dae159" /> | The Management API, pipeline behaviour, replication logs, and Postgres replication terminology remain unchanged. ## To test - Open `/project/<ref>/database/pipelines` and confirm the Database navigation, page header, and pipeline breadcrumb say Pipelines. - Open `/project/<ref>/database/replication?source=bookmark#destinations` and a legacy pipeline detail URL. Confirm each redirects to the matching Pipelines URL while preserving parameters and fragments. - From the Pipelines page, open Add destination. Confirm no read-replica migration notice appears. - Open the Pipelines guide and confirm its Dashboard steps lead to Database > Pipelines. ## Before merge - [ ] Get changelog entry reviewed https://github.com/supabase/changelog/pull/262 and prepare to merge simultaneously <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added dedicated **Database > Pipelines** pages for pipeline lists and details. - Added permanent redirects from legacy Replication URLs to their corresponding Pipelines pages. - Read replica management links now open **Settings > Infrastructure**. - **Documentation** - Updated Pipelines setup, monitoring, troubleshooting, and usage guidance to reference the current dashboard locations. - Updated Realtime guidance to use **Database > Publications**. - **Updates** - Renamed dashboard navigation, breadcrumbs, commands, and keyboard shortcuts from **Replication** to **Pipelines**. - Removed the “Read replicas have moved” notification. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
180 lines
6.8 KiB
TypeScript
180 lines
6.8 KiB
TypeScript
import { useParams } from 'common'
|
|
import Link from 'next/link'
|
|
import { useRouter } from 'next/router'
|
|
import { useState } from 'react'
|
|
import {
|
|
Alert,
|
|
AlertDescription,
|
|
AlertDialog,
|
|
AlertDialogAction,
|
|
AlertDialogCancel,
|
|
AlertDialogContent,
|
|
AlertDialogDescription,
|
|
AlertDialogFooter,
|
|
AlertDialogHeader,
|
|
AlertDialogTitle,
|
|
AlertTitle,
|
|
Button,
|
|
DialogSection,
|
|
DialogSectionSeparator,
|
|
WarningIcon,
|
|
} from 'ui'
|
|
|
|
import { BackupsEmpty } from '../BackupsEmpty'
|
|
import { BackupsStorageAlert } from '../BackupsStorageAlert'
|
|
import type { Timezone } from './PITR.types'
|
|
import { getClientTimezone } from './PITR.utils'
|
|
import { PITRForm } from './PITRForm'
|
|
import PITRStatus from './PITRStatus'
|
|
import { FormHeader } from '@/components/ui/Forms/FormHeader'
|
|
import { useBackupsQuery } from '@/data/database/backups-query'
|
|
import { usePitrRestoreMutation } from '@/data/database/pitr-restore-mutation'
|
|
import { useSetProjectStatus } from '@/data/projects/project-detail-query'
|
|
import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
|
|
import { PROJECT_STATUS } from '@/lib/constants'
|
|
|
|
export const PITRSelection = () => {
|
|
const router = useRouter()
|
|
const { ref } = useParams()
|
|
|
|
const { data: backups } = useBackupsQuery({ projectRef: ref })
|
|
const { data: databases } = useReadReplicasQuery({ projectRef: ref })
|
|
const { setProjectStatus } = useSetProjectStatus()
|
|
|
|
const [showConfiguration, setShowConfiguration] = useState(false)
|
|
const [showConfirmation, setShowConfirmation] = useState(false)
|
|
const [selectedTimezone, setSelectedTimezone] = useState<Timezone>(getClientTimezone())
|
|
const [selectedRecoveryPoint, setSelectedRecoveryPoint] = useState<{
|
|
selectedTimezone: Timezone
|
|
recoveryTimeTargetUnix: number
|
|
recoveryTimeString: string
|
|
recoveryTimeStringUtc: string
|
|
}>()
|
|
|
|
const hasReadReplicas = (databases ?? []).length > 1
|
|
|
|
const { mutateAsync: restoreFromPitr } = usePitrRestoreMutation({
|
|
onSuccess: (_, variables) => {
|
|
setTimeout(() => {
|
|
setShowConfirmation(false)
|
|
setProjectStatus({ ref: variables.ref, status: PROJECT_STATUS.RESTORING })
|
|
router.push(`/project/${variables.ref}`)
|
|
}, 3000)
|
|
},
|
|
})
|
|
|
|
const { earliestPhysicalBackupDateUnix, latestPhysicalBackupDateUnix } =
|
|
backups?.physicalBackupData ?? {}
|
|
const hasNoBackupsAvailable = !earliestPhysicalBackupDateUnix || !latestPhysicalBackupDateUnix
|
|
|
|
const onConfirmRestore = async () => {
|
|
if (!ref) return console.error('Project ref is required')
|
|
if (!selectedRecoveryPoint?.recoveryTimeTargetUnix)
|
|
return console.error('Recovery time target unix is required')
|
|
|
|
await restoreFromPitr({
|
|
ref,
|
|
recovery_time_target_unix: selectedRecoveryPoint.recoveryTimeTargetUnix,
|
|
})
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<FormHeader
|
|
title="Restore your database from a backup"
|
|
description="Database changes are watched and recorded, so that you can restore your database to any point in time"
|
|
/>
|
|
<BackupsStorageAlert />
|
|
{hasNoBackupsAvailable ? (
|
|
<BackupsEmpty />
|
|
) : (
|
|
<>
|
|
{hasReadReplicas && (
|
|
<Alert variant="warning">
|
|
<WarningIcon />
|
|
<AlertTitle>
|
|
Unable to restore from PITR as project has read replicas enabled
|
|
</AlertTitle>
|
|
<AlertDescription>
|
|
You will need to remove all read replicas first from your project's infrastructure
|
|
settings prior to starting a PITR restore.
|
|
</AlertDescription>
|
|
<div className="flex items-center gap-x-2 mt-2">
|
|
<Button asChild>
|
|
<Link href={`/project/${ref}/settings/infrastructure`}>Manage read replicas</Link>
|
|
</Button>
|
|
</div>
|
|
</Alert>
|
|
)}
|
|
{!showConfiguration ? (
|
|
<PITRStatus
|
|
selectedTimezone={selectedTimezone}
|
|
onUpdateTimezone={setSelectedTimezone}
|
|
onSetConfiguration={() => setShowConfiguration(true)}
|
|
/>
|
|
) : (
|
|
<PITRForm
|
|
earliestAvailableBackupUnix={earliestPhysicalBackupDateUnix}
|
|
latestAvailableBackupUnix={latestPhysicalBackupDateUnix}
|
|
onSubmit={(recoveryPoint) => {
|
|
setSelectedRecoveryPoint(recoveryPoint)
|
|
setShowConfirmation(true)
|
|
}}
|
|
/>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
<AlertDialog open={showConfirmation} onOpenChange={(open) => setShowConfirmation(open)}>
|
|
<AlertDialogContent size="medium">
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>Point in time recovery review</AlertDialogTitle>
|
|
<AlertDialogDescription asChild>
|
|
<div className="flex flex-col space-y-2">
|
|
<p className="text-sm text-foreground-light">Your database will be restored to:</p>
|
|
<div className="py-2 flex flex-col gap-3">
|
|
<div>
|
|
<p className="text-sm font-mono text-foreground-lighter">
|
|
{selectedRecoveryPoint?.selectedTimezone.text}
|
|
</p>
|
|
<p className="text-2xl">{selectedRecoveryPoint?.recoveryTimeString}</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-mono text-foreground-lighter">(UTC+00:00)</p>
|
|
<p className="text-2xl">{selectedRecoveryPoint?.recoveryTimeStringUtc}</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</AlertDialogDescription>
|
|
<DialogSectionSeparator />
|
|
<DialogSection>
|
|
<Alert variant="warning">
|
|
<WarningIcon />
|
|
<AlertTitle>This action cannot be undone, not canceled once started</AlertTitle>
|
|
<AlertDescription>
|
|
Any changes made to your database after this point in time will be lost. This
|
|
includes any changes to your project's storage and authentication.
|
|
</AlertDescription>
|
|
</Alert>
|
|
</DialogSection>
|
|
<DialogSectionSeparator />
|
|
<DialogSection>
|
|
<p className="text-sm text-foreground-light">
|
|
Restores may take from a few minutes up to several hours depending on the size of
|
|
your database. During this period, your project will not be available, until the
|
|
restoration is completed.
|
|
</p>
|
|
</DialogSection>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
<AlertDialogAction variant="warning" onClick={onConfirmRestore}>
|
|
I understand, begin restore
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogHeader>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</>
|
|
)
|
|
}
|