import { zodResolver } from '@hookform/resolvers/zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { capitalize } from 'lodash'
import { Fragment, useEffect, useMemo } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'
import { toast } from 'sonner'
import z from 'zod'
import { useParams } from 'common'
import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext'
import AlertError from 'components/ui/AlertError'
import { DocsButton } from 'components/ui/DocsButton'
import { setValueAsNullableNumber } from 'components/ui/Forms/Form.constants'
import { FormActions } from 'components/ui/Forms/FormActions'
import { InlineLink } from 'components/ui/InlineLink'
import Panel from 'components/ui/Panel'
import { useMaxConnectionsQuery } from 'data/database/max-connections-query'
import { usePgbouncerConfigQuery } from 'data/database/pgbouncer-config-query'
import { usePgbouncerConfigurationUpdateMutation } from 'data/database/pgbouncer-config-update-mutation'
import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query'
import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
import { useDatabaseSettingsStateSnapshot } from 'state/database-settings'
import {
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
Alert_Shadcn_,
Badge,
FormControl_Shadcn_,
FormField_Shadcn_,
Form_Shadcn_,
Input_Shadcn_,
Separator,
} from 'ui'
import { Admonition } from 'ui-patterns'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import ShimmeringLoader from 'ui-patterns/ShimmeringLoader'
import { POOLING_OPTIMIZATIONS } from './ConnectionPooling.constants'
const formId = 'pooling-configuration-form'
const PoolingConfigurationFormSchema = z.object({
default_pool_size: z.number().nullable(),
max_client_conn: z.number().nullable(),
})
/**
* [Joshen] PgBouncer configuration will be the main endpoint for GET and PATCH of pooling config
*/
export const ConnectionPooling = () => {
const { ref: projectRef } = useParams()
const { project } = useProjectContext()
const org = useSelectedOrganization()
const snap = useDatabaseSettingsStateSnapshot()
const canUpdateConnectionPoolingConfiguration = useCheckPermissions(
PermissionAction.UPDATE,
'projects',
{ resource: { project_id: project?.id } }
)
const {
data: pgbouncerConfig,
error: pgbouncerConfigError,
isLoading: isLoadingPgbouncerConfig,
isError: isErrorPgbouncerConfig,
isSuccess: isSuccessPgbouncerConfig,
} = usePgbouncerConfigQuery({ projectRef })
const disablePoolModeSelection = useMemo(() => {
return org?.plan?.id === 'free'
}, [org])
const { data: maxConnData } = useMaxConnectionsQuery({
projectRef: project?.ref,
connectionString: project?.connectionString,
})
const { data: addons, isSuccess: isSuccessAddons } = useProjectAddonsQuery({ projectRef })
const { mutate: updatePoolerConfig, isLoading: isUpdatingPoolerConfig } =
usePgbouncerConfigurationUpdateMutation()
const form = useForm Connection pooling configuration
If your network only supports IPv4, consider purchasing the{' '}
The maximum number of concurrent client connections allowed. This value is fixed at {defaultMaxClientConn} based on your compute size of{' '} {computeSize} and cannot be changed.
Please refer to our{' '}