RestartReplicaConfirmationModal.tsx 3.3 KB

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