ReadReplicaEligibilityWarnings.tsx247 lines · main
| 1 | import { SupportCategories } from '@supabase/shared-types/out/constants' |
| 2 | import { useParams } from 'common' |
| 3 | import Link from 'next/link' |
| 4 | import { useEffect, useState } from 'react' |
| 5 | import { toast } from 'sonner' |
| 6 | import { Button } from 'ui' |
| 7 | import { Admonition } from 'ui-patterns' |
| 8 | |
| 9 | import { useCheckEligibilityDeployReplica } from './useCheckEligibilityDeployReplica' |
| 10 | import { SupportLink } from '@/components/interfaces/Support/SupportLink' |
| 11 | import { DocsButton } from '@/components/ui/DocsButton' |
| 12 | import { UpgradePlanButton } from '@/components/ui/UpgradePlanButton' |
| 13 | import { useEnablePhysicalBackupsMutation } from '@/data/database/enable-physical-backups-mutation' |
| 14 | import { useProjectDetailQuery } from '@/data/projects/project-detail-query' |
| 15 | import { READ_REPLICAS_MAX_COUNT } from '@/data/read-replicas/replicas-query' |
| 16 | import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization' |
| 17 | import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' |
| 18 | import { DOCS_URL } from '@/lib/constants' |
| 19 | |
| 20 | export const ReadReplicaEligibilityWarnings = () => { |
| 21 | const { ref: projectRef } = useParams() |
| 22 | const { data: org } = useSelectedOrganizationQuery() |
| 23 | const { data: project } = useSelectedProjectQuery() |
| 24 | |
| 25 | const [refetchInterval, setRefetchInterval] = useState<number | false>(false) |
| 26 | |
| 27 | const { |
| 28 | hasOverdueInvoices, |
| 29 | isAWSProvider, |
| 30 | isAwsK8s, |
| 31 | isPgVersionBelow15, |
| 32 | isBelowSmallCompute, |
| 33 | isWalgNotEnabled, |
| 34 | isProWithSpendCapEnabled, |
| 35 | isReachedMaxReplicas, |
| 36 | maxNumberOfReplicas, |
| 37 | } = useCheckEligibilityDeployReplica() |
| 38 | |
| 39 | const { data: projectDetail, isSuccess: isProjectDetailSuccess } = useProjectDetailQuery( |
| 40 | { ref: projectRef }, |
| 41 | { |
| 42 | refetchInterval, |
| 43 | refetchOnWindowFocus: false, |
| 44 | } |
| 45 | ) |
| 46 | |
| 47 | const { mutate: enablePhysicalBackups, isPending: isEnabling } = useEnablePhysicalBackupsMutation( |
| 48 | { |
| 49 | onSuccess: () => { |
| 50 | toast.success( |
| 51 | 'Physical backups are currently being enabled, please check back in a few minutes!' |
| 52 | ) |
| 53 | setRefetchInterval(5000) |
| 54 | }, |
| 55 | } |
| 56 | ) |
| 57 | |
| 58 | useEffect(() => { |
| 59 | if (!isProjectDetailSuccess) return |
| 60 | if (projectDetail.is_physical_backups_enabled) { |
| 61 | setRefetchInterval(false) |
| 62 | } |
| 63 | }, [projectDetail?.is_physical_backups_enabled, isProjectDetailSuccess]) |
| 64 | |
| 65 | if (hasOverdueInvoices) { |
| 66 | return ( |
| 67 | <Admonition type="warning" title="Your organization has overdue invoices"> |
| 68 | <p>Please resolve all outstanding invoices first before deploying a new read replica</p> |
| 69 | <Button asChild type="default" className="mt-2"> |
| 70 | <Link href={`/org/${org?.slug}/billing#invoices`}>View invoices</Link> |
| 71 | </Button> |
| 72 | </Admonition> |
| 73 | ) |
| 74 | } |
| 75 | |
| 76 | if (!isAWSProvider) { |
| 77 | return ( |
| 78 | <Admonition |
| 79 | type="warning" |
| 80 | title="Read replicas are only supported for projects provisioned via AWS" |
| 81 | > |
| 82 | <p> |
| 83 | Projects provisioned by other cloud providers currently will not be able to use read |
| 84 | replicas |
| 85 | </p> |
| 86 | <DocsButton |
| 87 | abbrev={false} |
| 88 | className="mt-2" |
| 89 | href={`${DOCS_URL}/guides/platform/read-replicas#prerequisites`} |
| 90 | /> |
| 91 | </Admonition> |
| 92 | ) |
| 93 | } |
| 94 | |
| 95 | if (isAwsK8s) { |
| 96 | return ( |
| 97 | <Admonition |
| 98 | type="warning" |
| 99 | title="Read replicas are not supported for AWS (Revamped) projects" |
| 100 | description="Projects provisioned by other cloud providers currently will not be able to use read replicas" |
| 101 | /> |
| 102 | ) |
| 103 | } |
| 104 | |
| 105 | if (isPgVersionBelow15) { |
| 106 | return ( |
| 107 | <Admonition |
| 108 | type="warning" |
| 109 | title="Read replicas can only be deployed with projects on Postgres version 15 and above" |
| 110 | > |
| 111 | <p>If you'd like to use read replicas, please contact us via support</p> |
| 112 | <Button asChild type="default" className="mt-2"> |
| 113 | <SupportLink |
| 114 | queryParams={{ |
| 115 | projectRef, |
| 116 | category: SupportCategories.SALES_ENQUIRY, |
| 117 | subject: 'Enquiry on read replicas', |
| 118 | message: `Project DB version: ${project?.dbVersion}`, |
| 119 | }} |
| 120 | > |
| 121 | Contact support |
| 122 | </SupportLink> |
| 123 | </Button> |
| 124 | </Admonition> |
| 125 | ) |
| 126 | } |
| 127 | |
| 128 | if (isBelowSmallCompute) { |
| 129 | return ( |
| 130 | <Admonition type="warning" title="Project required to at least be on a Small compute"> |
| 131 | <p> |
| 132 | This is to ensure that read replicas can keep up with the primary databases' activities. |
| 133 | </p> |
| 134 | <div className="flex items-center gap-x-2 mt-2"> |
| 135 | <UpgradePlanButton |
| 136 | variant="default" |
| 137 | plan="Pro" |
| 138 | addon="computeSize" |
| 139 | source="read-replicas" |
| 140 | featureProposition="deploy Read Replicas" |
| 141 | /> |
| 142 | <DocsButton href={`${DOCS_URL}/guides/platform/read-replicas#prerequisites`} /> |
| 143 | </div> |
| 144 | </Admonition> |
| 145 | ) |
| 146 | } |
| 147 | |
| 148 | if (isWalgNotEnabled) { |
| 149 | return ( |
| 150 | <Admonition |
| 151 | type="warning" |
| 152 | title={ |
| 153 | refetchInterval === false |
| 154 | ? 'Physical backups are required to deploy replicas' |
| 155 | : 'Physical backups are currently being enabled' |
| 156 | } |
| 157 | > |
| 158 | {refetchInterval === false ? ( |
| 159 | <> |
| 160 | <p> |
| 161 | Physical backups are used under the hood to spin up read replicas for your project. |
| 162 | </p> |
| 163 | <p> |
| 164 | Enabling physical backups will take a few minutes, after which you will be able to |
| 165 | deploy read replicas. |
| 166 | </p> |
| 167 | </> |
| 168 | ) : ( |
| 169 | <> |
| 170 | <p> |
| 171 | This warning will go away once physical backups have been enabled - check back in a |
| 172 | few minutes! |
| 173 | </p> |
| 174 | <p>You may start deploying read replicas thereafter once this is completed.</p> |
| 175 | </> |
| 176 | )} |
| 177 | {refetchInterval === false && ( |
| 178 | <div className="flex items-center gap-x-2 mt-2"> |
| 179 | <Button |
| 180 | type="default" |
| 181 | loading={isEnabling} |
| 182 | disabled={isEnabling} |
| 183 | onClick={() => { |
| 184 | if (projectRef) enablePhysicalBackups({ ref: projectRef }) |
| 185 | }} |
| 186 | > |
| 187 | Enable physical backups |
| 188 | </Button> |
| 189 | <DocsButton |
| 190 | abbrev={false} |
| 191 | href={`${DOCS_URL}/guides/platform/read-replicas#how-are-read-replicas-made`} |
| 192 | /> |
| 193 | </div> |
| 194 | )} |
| 195 | </Admonition> |
| 196 | ) |
| 197 | } |
| 198 | |
| 199 | if (isProWithSpendCapEnabled) { |
| 200 | return ( |
| 201 | <Admonition type="warning" title="Spend cap needs to be disabled to deploy replicas"> |
| 202 | <p> |
| 203 | Launching a replica incurs additional disk size that will exceed the plan's quota. Disable |
| 204 | the spend cap first to allow overages before launching a replica. |
| 205 | </p> |
| 206 | <UpgradePlanButton |
| 207 | variant="default" |
| 208 | source="read-replicas" |
| 209 | addon="spendCap" |
| 210 | className="mt-2" |
| 211 | > |
| 212 | Disable spend cap |
| 213 | </UpgradePlanButton> |
| 214 | </Admonition> |
| 215 | ) |
| 216 | } |
| 217 | |
| 218 | if (isReachedMaxReplicas) { |
| 219 | return ( |
| 220 | <Admonition |
| 221 | type="warning" |
| 222 | title={`You can only deploy up to ${maxNumberOfReplicas} read replicas at once`} |
| 223 | > |
| 224 | <p>If you'd like to spin up another read replica, please drop an existing replica first.</p> |
| 225 | {maxNumberOfReplicas < READ_REPLICAS_MAX_COUNT && ( |
| 226 | <> |
| 227 | <p> |
| 228 | Alternatively, you may deploy up to{' '} |
| 229 | <span className="text-foreground">{READ_REPLICAS_MAX_COUNT}</span> replicas if your |
| 230 | project is on an XL compute or higher. |
| 231 | </p> |
| 232 | <UpgradePlanButton |
| 233 | variant="default" |
| 234 | plan="Pro" |
| 235 | addon="computeSize" |
| 236 | source="read-replicas" |
| 237 | featureProposition="deploy Read Replicas" |
| 238 | className="mt-2" |
| 239 | > |
| 240 | Change compute size |
| 241 | </UpgradePlanButton> |
| 242 | </> |
| 243 | )} |
| 244 | </Admonition> |
| 245 | ) |
| 246 | } |
| 247 | } |