mirror of
https://github.com/supabase/supabase.git
synced 2026-10-06 09:55:06 +03:00
Update disk size reduction validation (#30070)
* Update disk size reduction validation * Fix * Add docs * Small fix
This commit is contained in:
1 parent
9a3d0992c3
commit
fa4ce4a949
4 files changed
+110
-73
No files matched your search
@@ -132,3 +132,5 @@ set default_transaction_read_only = 'off';
|
||||
### Reducing disk size
|
||||
|
||||
Disks don't automatically downsize during normal operation. Once you have [reduced your database size](/docs/guides/platform/database-size#database-size), they _will_ automatically "right-size" during a [project upgrade](/docs/guides/platform/upgrading). The final disk size after the upgrade is 1.2x the size of the database with a minimum of 8 GB. For example, if your database size is 100GB, and you have a 200GB disk, the size after a project upgrade will be 120 GB.
|
||||
|
||||
In the event that your project is already on the latest version of Postgres and cannot be upgraded, a new version of Postgres will be released approximately every week which you can then upgrade to once it becomes available.
|
||||
@@ -1,7 +1,7 @@
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
import { AnimatePresence, motion } from 'framer-motion'
|
||||
import { HelpCircle, InfoIcon, RotateCcw } from 'lucide-react'
|
||||
import { ExternalLink, HelpCircle, InfoIcon, RotateCcw } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
@@ -60,7 +60,7 @@ import {
|
||||
calculateIOPSPrice,
|
||||
calculateThroughputPrice,
|
||||
} from './DiskManagement.utils'
|
||||
import { DiskStorageSchema, DiskStorageSchemaType } from './DiskManagementPanelSchema'
|
||||
import { getDiskStorageSchema, DiskStorageSchemaType } from './DiskManagementPanelSchema'
|
||||
import { DiskManagementPlanUpgradeRequired } from './DiskManagementPlanUpgradeRequired'
|
||||
import {
|
||||
DiskManagementDiskSizeReadReplicas,
|
||||
@@ -68,6 +68,8 @@ import {
|
||||
DiskManagementThroughputReadReplicas,
|
||||
} from './DiskManagementReadReplicas'
|
||||
import { DiskManagementReviewAndSubmitDialog } from './DiskManagementReviewAndSubmitDialog'
|
||||
import { Admonition } from 'ui-patterns'
|
||||
import { Markdown } from '../Markdown'
|
||||
|
||||
export function DiskManagementPanelForm() {
|
||||
const { project } = useProjectContext()
|
||||
@@ -161,6 +163,7 @@ export function DiskManagementPanelForm() {
|
||||
throughput: throughput_mbps,
|
||||
totalSize: size_gb,
|
||||
}
|
||||
const DiskStorageSchema = getDiskStorageSchema(size_gb)
|
||||
const form = useForm<DiskStorageSchemaType>({
|
||||
resolver: zodResolver(DiskStorageSchema),
|
||||
defaultValues,
|
||||
@@ -616,8 +619,31 @@ export function DiskManagementPanelForm() {
|
||||
label="Disk Size"
|
||||
layout="horizontal"
|
||||
description={
|
||||
includedDiskGB > 0 &&
|
||||
`Your plan includes ${includedDiskGB} GB of disk size for ${watchedStorageType}.`
|
||||
<>
|
||||
{includedDiskGB > 0 &&
|
||||
`Your plan includes ${includedDiskGB} GB of disk size for ${watchedStorageType}.`}
|
||||
{field.value < size_gb && (
|
||||
<Admonition
|
||||
className="mt-2"
|
||||
type="default"
|
||||
title="Reducing your project's disk size?"
|
||||
description={
|
||||
<Markdown
|
||||
className="[&>p]:!leading-normal"
|
||||
content={`Your disk size will automatically "right-size" when you [upgrade your project](/project/${projectRef}/settings/infrastructure).`}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-x-2">
|
||||
<Button asChild type="default" icon={<ExternalLink />}>
|
||||
<Link href="https://supabase.com/docs/guides/platform/database-size#reducing-disk-size">
|
||||
Documentation
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</Admonition>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
>
|
||||
<div className="mt-1 relative flex gap-2 items-center">
|
||||
|
||||
@@ -11,89 +11,98 @@ const baseSchema = z.object({
|
||||
throughput: z.number().optional().describe('Throughput in MB/s for gp3'),
|
||||
})
|
||||
|
||||
export const DiskStorageSchema = baseSchema.superRefine((data, ctx) => {
|
||||
const { storageType, totalSize, provisionedIOPS, throughput } = data
|
||||
export const getDiskStorageSchema = (currentDiskSize: number) =>
|
||||
baseSchema.superRefine((data, ctx) => {
|
||||
const { storageType, totalSize, provisionedIOPS, throughput } = data
|
||||
|
||||
if (storageType === 'io2') {
|
||||
// Validation rules for io2
|
||||
const maxIOPS = Math.min(1000 * totalSize, 256000)
|
||||
if (provisionedIOPS < 100) {
|
||||
if (totalSize < currentDiskSize) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Provisioned IOPS must be at least 100',
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
} else if (provisionedIOPS > maxIOPS) {
|
||||
if (totalSize >= 8) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Provisioned IOPS must be at most ${maxIOPS}.`,
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
} else {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Invalid IOPS value due to invalid disk size`,
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
}
|
||||
}
|
||||
if (throughput !== undefined) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Throughput is not configurable for io2.',
|
||||
path: ['throughput'],
|
||||
})
|
||||
}
|
||||
if (totalSize > DISK_LIMITS[DiskType.IO2].maxStorage) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Allocated disksize must not exceed 61,440 GB',
|
||||
message: 'Disk size cannot be reduced from current configuration',
|
||||
path: ['totalSize'],
|
||||
})
|
||||
}
|
||||
} else if (storageType === 'gp3') {
|
||||
// Validation rules for gp3
|
||||
const maxIOPS = Math.min(500 * totalSize, 16000)
|
||||
const maxThroughput = Math.min(0.25 * provisionedIOPS, 1000)
|
||||
|
||||
if (provisionedIOPS < 3000) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Provisioned IOPS must be at least 3000`,
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
} else if (provisionedIOPS > maxIOPS) {
|
||||
if (totalSize >= 8) {
|
||||
if (storageType === 'io2') {
|
||||
// Validation rules for io2
|
||||
const maxIOPS = Math.min(1000 * totalSize, 256000)
|
||||
if (provisionedIOPS < 100) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Provisioned IOPS must be at most ${maxIOPS}`,
|
||||
message: 'Provisioned IOPS must be at least 100',
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
} else {
|
||||
} else if (provisionedIOPS > maxIOPS) {
|
||||
if (totalSize >= 8) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Provisioned IOPS must be at most ${maxIOPS}.`,
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
} else {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Invalid IOPS value due to invalid disk size`,
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
}
|
||||
}
|
||||
if (throughput !== undefined) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Invalid IOPS value due to invalid disk size`,
|
||||
message: 'Throughput is not configurable for io2.',
|
||||
path: ['throughput'],
|
||||
})
|
||||
}
|
||||
if (totalSize > DISK_LIMITS[DiskType.IO2].maxStorage) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Allocated disk size must not exceed 61,440 GB',
|
||||
path: ['totalSize'],
|
||||
})
|
||||
}
|
||||
} else if (storageType === 'gp3') {
|
||||
// Validation rules for gp3
|
||||
const maxIOPS = Math.min(500 * totalSize, 16000)
|
||||
const maxThroughput = Math.min(0.25 * provisionedIOPS, 1000)
|
||||
|
||||
if (provisionedIOPS < 3000) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Provisioned IOPS must be at least 3000`,
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
} else if (provisionedIOPS > maxIOPS) {
|
||||
if (totalSize >= 8) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Provisioned IOPS must be at most ${maxIOPS}`,
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
} else {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Invalid IOPS value due to invalid disk size`,
|
||||
path: ['provisionedIOPS'],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (throughput !== undefined && (throughput < 125 || throughput > maxThroughput)) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Throughput must be set between 125 and ${maxThroughput?.toLocaleString()} MB/s.`,
|
||||
path: ['throughput'],
|
||||
})
|
||||
}
|
||||
if (totalSize > DISK_LIMITS[DiskType.GP3].maxStorage) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Allocated disk size must not exceed 16,384 GB',
|
||||
path: ['totalSize'],
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (throughput !== undefined && (throughput < 125 || throughput > maxThroughput)) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `Throughput must be set between 125 and ${maxThroughput?.toLocaleString()} MB/s.`,
|
||||
path: ['throughput'],
|
||||
})
|
||||
}
|
||||
if (totalSize > DISK_LIMITS[DiskType.GP3].maxStorage) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: 'Allocated disksize must not exceed 16,384 GB',
|
||||
path: ['totalSize'],
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export type DiskStorageSchemaType = z.infer<typeof DiskStorageSchema>
|
||||
export type DiskStorageSchemaType = z.infer<ReturnType<typeof getDiskStorageSchema>>
|
||||
+1
-1
@@ -207,7 +207,7 @@ const InstanceConfigurationUI = () => {
|
||||
}, [isSuccessReplicas, isSuccessLoadBalancers, nodes, edges, view])
|
||||
|
||||
return (
|
||||
<div className="nowheel">
|
||||
<div className="nowheel border-y">
|
||||
<div
|
||||
className={`h-[500px] w-full relative ${
|
||||
isSuccessReplicas && !isLoadingProject ? '' : 'flex items-center justify-center px-28'
|
||||
|
||||
Reference in new issue
Block a user