mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 19:05:06 +03:00
Updates the dashboard disk-management copy to match the new AWS EBS modification limits (already reflected in the docs): from the old fixed "4-hour cooldown / once every 4 hours" framing to "up to 4 modifications within a rolling 24-hour window". This is a copy-only change plus one small logic-constant alignment. Timer/countdown behavior is unchanged — this only updates wording to bring the dashboard in line with the docs. **Changed:** - `DiskSpaceBar` autoscaling tooltip, `DiskCountdownRadial` card, `DiskSizeConfiguration` "Importing a lot of data?" alert, `DiskSizeConfigurationModal` alert title + both countdown branches, `DiskManagementReviewAndSubmitDialog` IOPS + disk-size row descriptions, and two code comments — all reworded to the new "4 per rolling 24-hour window" framing - `DiskSizeConfigurationModal` countdown now derives from the shared `COOLDOWN_DURATION` constant (4h) instead of a stale hardcoded `6 * 60` (6h), so the legacy resize path matches the newer disk-attributes path ## To test - Open a Pro AWS project → **Settings → Compute and Disk** → hover the **Autoscaling** pill on the disk bar: tooltip should read "…limited to 4 within a rolling 24-hour window" (no "once every 4 hours") - Change IOPS only → **Review changes** → IOPS row description shows the new "rolling 24-hour window… as soon as the previous one completes" copy - Change disk size → **Review changes** → Disk size row shows "You can modify disk attributes up to 4 times within a rolling 24-hour window" (not "For 4 hours after changes…") - On a non-AWS Pro project → **Database → Settings → Increase disk size**: modal title reads "Disk modifications are limited to 4 per rolling 24-hour window"; any "resize again in ~X" countdown is bounded by 4 hours, not 6 - Sanity: none of the old "4-hour cooldown" / "once every 4 hours" strings appear anywhere in the disk UI <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Updated disk resizing messages across the app to reflect a rolling 24-hour limit instead of a fixed 4-hour cooldown. * Clarified when disk size, IOPS, and throughput changes are available again, including more accurate next-available timing. * Improved warning copy in disk configuration and review dialogs so limit messages are consistent and easier to understand. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Alaister Young <10985857+alaister@users.noreply.github.com>
207 lines
6.8 KiB
TypeScript
207 lines
6.8 KiB
TypeScript
import { useMemo } from 'react'
|
|
import { UseFormReturn } from 'react-hook-form'
|
|
|
|
import { DiskStorageSchemaType } from '../DiskManagement.schema'
|
|
import { ComputeInstanceAddonVariantId } from '../DiskManagement.types'
|
|
import {
|
|
calculateComputeSizePrice,
|
|
calculateDiskSizePrice,
|
|
calculateIOPSPrice,
|
|
calculateThroughputPrice,
|
|
getAvailableComputeOptions,
|
|
mapAddOnVariantIdToComputeSize,
|
|
} from '../DiskManagement.utils'
|
|
import { DiskType } from '../ui/DiskManagement.constants'
|
|
import { useProjectAddonsQuery } from '@/data/subscriptions/project-addons-query'
|
|
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
|
import {
|
|
useIsAwsNimbusCloudProvider,
|
|
useSelectedProjectQuery,
|
|
} from '@/hooks/misc/useSelectedProject'
|
|
|
|
const COMPUTE_SIZES_BELOW_LARGE: Array<ComputeInstanceAddonVariantId> = [
|
|
'ci_nano',
|
|
'ci_micro',
|
|
'ci_small',
|
|
'ci_medium',
|
|
]
|
|
|
|
export function useDiskManagementReviewChanges(
|
|
form: UseFormReturn<DiskStorageSchemaType>,
|
|
numReplicas: number
|
|
) {
|
|
const { data: project } = useSelectedProjectQuery()
|
|
const { data: org } = useSelectedOrganizationQuery()
|
|
const isAwsNimbus = useIsAwsNimbusCloudProvider()
|
|
const { data: addons } = useProjectAddonsQuery({ projectRef: project?.ref })
|
|
|
|
const isAwsK8sProject = project?.cloud_provider === 'AWS_K8S'
|
|
const planId = org?.plan.id ?? 'free'
|
|
|
|
const availableAddons = useMemo(() => addons?.available_addons ?? [], [addons])
|
|
const availableOptions = useMemo(
|
|
() => getAvailableComputeOptions(availableAddons, project?.cloud_provider),
|
|
[availableAddons, project?.cloud_provider]
|
|
)
|
|
|
|
// --- Prices ---
|
|
|
|
const computeSizePrice = calculateComputeSizePrice({
|
|
availableOptions,
|
|
oldComputeSize: form.formState.defaultValues?.computeSize || 'ci_micro',
|
|
newComputeSize: form.getValues('computeSize'),
|
|
plan: planId,
|
|
})
|
|
const diskSizePrice = calculateDiskSizePrice({
|
|
planId,
|
|
oldSize: form.formState.defaultValues?.totalSize || 0,
|
|
oldStorageType: form.formState.defaultValues?.storageType as DiskType,
|
|
newSize: form.getValues('totalSize'),
|
|
newStorageType: form.getValues('storageType') as DiskType,
|
|
numReplicas,
|
|
})
|
|
const iopsPrice = calculateIOPSPrice({
|
|
oldStorageType: form.formState.defaultValues?.storageType as DiskType,
|
|
oldProvisionedIOPS: form.formState.defaultValues?.provisionedIOPS || 0,
|
|
newStorageType: form.getValues('storageType') as DiskType,
|
|
newProvisionedIOPS: form.getValues('provisionedIOPS'),
|
|
numReplicas,
|
|
})
|
|
const throughputPrice = calculateThroughputPrice({
|
|
storageType: form.getValues('storageType') as DiskType,
|
|
newThroughput: form.getValues('throughput') || 0,
|
|
oldThroughput: form.formState.defaultValues?.throughput || 0,
|
|
numReplicas,
|
|
})
|
|
|
|
const totalBeforePrice =
|
|
Number(computeSizePrice.oldPrice) +
|
|
Number(diskSizePrice.oldPrice) +
|
|
Number(iopsPrice.oldPrice) +
|
|
Number(throughputPrice.oldPrice)
|
|
|
|
const totalAfterPrice =
|
|
Number(computeSizePrice.newPrice) +
|
|
Number(diskSizePrice.newPrice) +
|
|
Number(iopsPrice.newPrice) +
|
|
Number(throughputPrice.newPrice)
|
|
|
|
// --- Change flags ---
|
|
|
|
const hasComputeChanges =
|
|
form.formState.defaultValues?.computeSize !== form.getValues('computeSize')
|
|
|
|
const hasTotalSizeChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.totalSize !== form.getValues('totalSize')
|
|
|
|
const hasStorageTypeChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.storageType !== form.getValues('storageType')
|
|
|
|
const hasThroughputChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.throughput !== form.getValues('throughput')
|
|
|
|
const hasIOPSChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.provisionedIOPS !== form.getValues('provisionedIOPS')
|
|
|
|
const hasGrowthPercentChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.growthPercent !== form.getValues('growthPercent')
|
|
|
|
const hasMinIncrementChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.minIncrementGb !== form.getValues('minIncrementGb')
|
|
|
|
const hasMaxSizeChanges =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
form.formState.defaultValues?.maxSizeGb !== form.getValues('maxSizeGb')
|
|
|
|
// --- Derived predicates ---
|
|
|
|
const storageTypeAfter = form.getValues('storageType') as DiskType
|
|
|
|
// Show hero whenever any line-item price actually changes, not just compute
|
|
const anyBillableDiskChange =
|
|
Number(diskSizePrice.newPrice) !== Number(diskSizePrice.oldPrice) ||
|
|
Number(iopsPrice.newPrice) !== Number(iopsPrice.oldPrice) ||
|
|
Number(throughputPrice.newPrice) !== Number(throughputPrice.oldPrice)
|
|
|
|
// Show cooldown warning whenever any disk attribute that counts toward the 24-hour modification limit changes
|
|
const anyDiskAttributeChange = hasIOPSChanges || hasStorageTypeChanges || hasTotalSizeChanges
|
|
|
|
// Show extended downtime warning when resizing to/from a size below large
|
|
const hasExtendedDowntimeRisk =
|
|
hasComputeChanges &&
|
|
(COMPUTE_SIZES_BELOW_LARGE.includes(
|
|
(form.formState.defaultValues?.computeSize ?? 'ci_nano') as ComputeInstanceAddonVariantId
|
|
) ||
|
|
COMPUTE_SIZES_BELOW_LARGE.includes(
|
|
form.getValues('computeSize') as ComputeInstanceAddonVariantId
|
|
))
|
|
|
|
// Throughput is only a user-configurable, separately-billed attribute for GP3. For IO2 it is
|
|
// derived from provisioned IOPS (0.256 MiB/s per IOPS) and isn't surfaced as its own value, so
|
|
// the form clears it to 0 — rendering a misleading "→ 0 MB/s". Only show the row when the
|
|
// resulting storage type is GP3; any GP3→IO2 throughput price delta still lands in the total.
|
|
const showThroughputRow =
|
|
!isAwsK8sProject &&
|
|
!isAwsNimbus &&
|
|
storageTypeAfter === 'gp3' &&
|
|
(hasThroughputChanges || hasStorageTypeChanges)
|
|
|
|
const hasAnyBreakdownRows =
|
|
hasComputeChanges ||
|
|
hasStorageTypeChanges ||
|
|
hasIOPSChanges ||
|
|
showThroughputRow ||
|
|
hasTotalSizeChanges ||
|
|
hasGrowthPercentChanges ||
|
|
hasMinIncrementChanges ||
|
|
hasMaxSizeChanges
|
|
|
|
// --- Labels ---
|
|
|
|
const oldComputeLabel = mapAddOnVariantIdToComputeSize(
|
|
form.formState.defaultValues?.computeSize ?? 'ci_nano'
|
|
)
|
|
const newComputeLabel = mapAddOnVariantIdToComputeSize(form.getValues('computeSize'))
|
|
|
|
return {
|
|
// prices
|
|
computeSizePrice,
|
|
diskSizePrice,
|
|
iopsPrice,
|
|
throughputPrice,
|
|
totalBeforePrice,
|
|
totalAfterPrice,
|
|
// change flags
|
|
hasComputeChanges,
|
|
hasTotalSizeChanges,
|
|
hasStorageTypeChanges,
|
|
hasThroughputChanges,
|
|
hasIOPSChanges,
|
|
hasGrowthPercentChanges,
|
|
hasMinIncrementChanges,
|
|
hasMaxSizeChanges,
|
|
// derived predicates
|
|
anyBillableDiskChange,
|
|
anyDiskAttributeChange,
|
|
showThroughputRow,
|
|
hasAnyBreakdownRows,
|
|
hasExtendedDowntimeRisk,
|
|
// labels
|
|
oldComputeLabel,
|
|
newComputeLabel,
|
|
}
|
|
}
|