RestartReplicaConfirmationModal.tsx93 lines · main
1import { useQueryClient } from '@tanstack/react-query'
2import { useParams } from 'common'
3import { toast } from 'sonner'
4import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
5
6import { REPLICA_STATUS } from './InstanceConfiguration.constants'
7import { useProjectRestartMutation } from '@/data/projects/project-restart-mutation'
8import { replicaKeys } from '@/data/read-replicas/keys'
9import { Database } from '@/data/read-replicas/replicas-query'
10import { formatDatabaseID } from '@/data/read-replicas/replicas.utils'
11
12interface RestartReplicaConfirmationModalProps {
13 selectedReplica?: Database
14 onSuccess: () => void
15 onCancel: () => void
16}
17
18export const RestartReplicaConfirmationModal = ({
19 selectedReplica,
20 onSuccess,
21 onCancel,
22}: RestartReplicaConfirmationModalProps) => {
23 const { ref } = useParams()
24 const queryClient = useQueryClient()
25 const formattedId = formatDatabaseID(selectedReplica?.identifier ?? '')
26
27 const { mutate: restartProject, isPending: isRestartingProject } = useProjectRestartMutation({
28 onSuccess: () => {
29 toast.success(`Restarting read replica (ID: ${formattedId})`)
30
31 // [Joshen] Temporarily optimistic rendering until API supports immediate status update
32 queryClient.setQueriesData({ queryKey: replicaKeys.list(ref) }, (old: Database[]) => {
33 const updatedReplicas = old.map((x) => {
34 if (x.identifier === selectedReplica?.identifier) {
35 return { ...x, status: REPLICA_STATUS.RESTARTING }
36 } else {
37 return x
38 }
39 })
40 return updatedReplicas
41 })
42
43 queryClient.setQueriesData({ queryKey: replicaKeys.statuses(ref) }, (old: Database[]) => {
44 const updatedReplicas = old.map((x) => {
45 if (x.identifier === selectedReplica?.identifier) {
46 return { ...x, status: REPLICA_STATUS.RESTARTING }
47 } else {
48 return x
49 }
50 })
51 return updatedReplicas
52 })
53
54 onSuccess()
55 onCancel()
56 },
57 onError: (error) => {
58 toast.error(`Failed to restart replica: ${error.message}`)
59 },
60 })
61
62 const onConfirmRestartReplica = () => {
63 if (!ref) return console.error('Project is required')
64 if (selectedReplica === undefined) return toast.error('No replica selected')
65 restartProject({ ref, identifier: selectedReplica.identifier })
66 }
67
68 return (
69 <ConfirmationModal
70 size="medium"
71 variant="warning"
72 loading={isRestartingProject}
73 visible={selectedReplica !== undefined}
74 title={`Confirm to restart selected replica? (ID: ${formattedId})`}
75 confirmLabel="Restart replica"
76 confirmLabelLoading="Restarting replica"
77 onCancel={() => onCancel()}
78 onConfirm={() => onConfirmRestartReplica()}
79 >
80 <p className="text-sm">
81 Your replica will be offline for a few minutes while it is being restarted. Before
82 restarting the replica, consider:
83 </p>
84 <ul className="text-sm text-foreground-light py-1 list-disc mx-4 space-y-1">
85 <li>
86 Network traffic from this region may slow down while the replica is restarting, especially
87 if you have no other replicas in this region
88 </li>
89 </ul>
90 <p className="text-sm mt-2">Are you sure you want to restart this replica now?</p>
91 </ConfirmationModal>
92 )
93}