mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
feat(replication): Implement new error UI when the pipeline fails (#37105)
This commit is contained in:
1 parent
0666d5c03e
commit
e3b646fea6
5 files changed
+424
-68
No files matched your search
@@ -4,9 +4,12 @@ import { ReplicationPipelinesData } from 'data/replication/pipelines-query'
|
||||
import { ResponseError } from 'types'
|
||||
import ShimmeringLoader from 'ui-patterns/ShimmeringLoader'
|
||||
import RowMenu from './RowMenu'
|
||||
import PipelineStatus, { PipelineStatusRequestStatus } from './PipelineStatus'
|
||||
import PipelineStatus, { PipelineStatusRequestStatus, PipelineStatusName } from './PipelineStatus'
|
||||
import { useParams } from 'common'
|
||||
import { useReplicationPipelineStatusQuery } from 'data/replication/pipeline-status-query'
|
||||
import {
|
||||
ReplicationPipelineStatusData,
|
||||
useReplicationPipelineStatusQuery,
|
||||
} from 'data/replication/pipeline-status-query'
|
||||
import { useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { useStartPipelineMutation } from 'data/replication/start-pipeline-mutation'
|
||||
@@ -65,10 +68,22 @@ const DestinationRow = ({
|
||||
const { mutateAsync: startPipeline } = useStartPipelineMutation()
|
||||
const { mutateAsync: stopPipeline } = useStopPipelineMutation()
|
||||
const pipelineStatus = pipelineStatusData?.status
|
||||
const getStatusName = (
|
||||
status: ReplicationPipelineStatusData['status'] | undefined
|
||||
): string | undefined => {
|
||||
if (status && typeof status === 'object' && 'name' in status) {
|
||||
return status.name
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
const statusName = getStatusName(pipelineStatus)
|
||||
if (
|
||||
(requestStatus === PipelineStatusRequestStatus.EnableRequested &&
|
||||
pipelineStatus === 'Started') ||
|
||||
(requestStatus === PipelineStatusRequestStatus.DisableRequested && pipelineStatus === 'Stopped')
|
||||
(statusName === PipelineStatusName.STARTED || statusName === PipelineStatusName.FAILED)) ||
|
||||
(requestStatus === PipelineStatusRequestStatus.DisableRequested &&
|
||||
(statusName === PipelineStatusName.STOPPED || statusName === PipelineStatusName.FAILED))
|
||||
) {
|
||||
setRequestStatus(PipelineStatusRequestStatus.None)
|
||||
}
|
||||
@@ -190,7 +205,7 @@ const DestinationRow = ({
|
||||
sourceId,
|
||||
destinationId: destinationId,
|
||||
pipelineId: pipeline?.id,
|
||||
enabled: pipelineStatusData?.status === 'Started',
|
||||
enabled: statusName === PipelineStatusName.STARTED,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -2,8 +2,21 @@ import AlertError from 'components/ui/AlertError'
|
||||
import ShimmeringLoader from 'ui-patterns/ShimmeringLoader'
|
||||
import { cn } from 'ui'
|
||||
import { ResponseError } from 'types'
|
||||
import { Loader2 } from 'lucide-react'
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from 'ui'
|
||||
import { Loader2, ChevronDown, ChevronRight, Copy, AlertTriangle } from 'lucide-react'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
Button,
|
||||
Collapsible_Shadcn_ as Collapsible,
|
||||
CollapsibleContent_Shadcn_ as CollapsibleContent,
|
||||
CollapsibleTrigger_Shadcn_ as CollapsibleTrigger,
|
||||
} from 'ui'
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
import { copyToClipboard } from 'ui'
|
||||
import { toast } from 'sonner'
|
||||
import { ReplicationPipelineStatusData } from 'data/replication/pipeline-status-query'
|
||||
|
||||
export enum PipelineStatusRequestStatus {
|
||||
None = 'None',
|
||||
@@ -11,8 +24,19 @@ export enum PipelineStatusRequestStatus {
|
||||
DisableRequested = 'DisableRequested',
|
||||
}
|
||||
|
||||
export enum PipelineStatusName {
|
||||
FAILED = 'failed',
|
||||
STARTING = 'starting',
|
||||
STARTED = 'started',
|
||||
STOPPED = 'stopped',
|
||||
UNKNOWN = 'unknown',
|
||||
}
|
||||
|
||||
// Type alias for better readability
|
||||
type FailedStatus = Extract<ReplicationPipelineStatusData['status'], { name: 'failed' }>
|
||||
|
||||
interface PipelineStatusProps {
|
||||
pipelineStatus: string | undefined
|
||||
pipelineStatus: ReplicationPipelineStatusData['status'] | undefined
|
||||
error: ResponseError | null
|
||||
isLoading: boolean
|
||||
isError: boolean
|
||||
@@ -28,6 +52,175 @@ const PipelineStatus = ({
|
||||
isSuccess,
|
||||
requestStatus,
|
||||
}: PipelineStatusProps) => {
|
||||
const [isErrorDetailsOpen, setIsErrorDetailsOpen] = useState(false)
|
||||
const errorDetailsRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (errorDetailsRef.current && !errorDetailsRef.current.contains(event.target as Node)) {
|
||||
setIsErrorDetailsOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (isErrorDetailsOpen) {
|
||||
document.addEventListener('mousedown', handleClickOutside)
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousedown', handleClickOutside)
|
||||
}
|
||||
}, [isErrorDetailsOpen])
|
||||
|
||||
const handleCopyToClipboard = async (text: string) => {
|
||||
try {
|
||||
await copyToClipboard(text)
|
||||
toast.success('Error details copied to clipboard')
|
||||
} catch (error) {
|
||||
toast.error('Failed to copy error details')
|
||||
}
|
||||
}
|
||||
|
||||
const isFailedStatus = (
|
||||
status: ReplicationPipelineStatusData['status'] | undefined
|
||||
): status is FailedStatus => {
|
||||
return (
|
||||
status !== null &&
|
||||
status !== undefined &&
|
||||
typeof status === 'object' &&
|
||||
status.name === PipelineStatusName.FAILED
|
||||
)
|
||||
}
|
||||
|
||||
const isLogLoadingState = (failedStatus: FailedStatus): boolean => {
|
||||
// Right now we hardcode the error message which is returned when k8s is not able to find logs, which seems
|
||||
// to be a transient error. In case we find a way to properly handle this in the backend, this hack will not
|
||||
// be needed anymore.
|
||||
return (
|
||||
failedStatus.message?.startsWith('unable to retrieve container logs for containerd://') ===
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
const renderFailedStatus = (failedStatus: FailedStatus) => {
|
||||
const hasDetails =
|
||||
failedStatus.message || failedStatus.reason || failedStatus.exit_code !== undefined
|
||||
const isLoadingLogs = isLogLoadingState(failedStatus)
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div className="flex items-center gap-2 text-sm text-destructive">
|
||||
{isLoadingLogs ? (
|
||||
<Loader2 className="w-3 h-3 animate-spin" />
|
||||
) : (
|
||||
<AlertTriangle className="w-3 h-3" />
|
||||
)}
|
||||
<span>Failed</span>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>
|
||||
{isLoadingLogs
|
||||
? 'Pipeline failed - logs are being retrieved from container'
|
||||
: 'Pipeline has failed - expand for error details'}
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
{hasDetails && (
|
||||
<Collapsible open={isErrorDetailsOpen} onOpenChange={setIsErrorDetailsOpen}>
|
||||
<CollapsibleTrigger asChild>
|
||||
<Button type="text" size="tiny" className="h-auto py-0 px-1 text-xs">
|
||||
{isErrorDetailsOpen ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
|
||||
</Button>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="absolute z-10 mt-1 left-0 min-w-[400px] max-w-[600px]">
|
||||
<div
|
||||
ref={errorDetailsRef}
|
||||
className="rounded-lg border border-border bg-surface-100 p-3 shadow-md"
|
||||
>
|
||||
{isLoadingLogs ? (
|
||||
<div className="flex items-center gap-3">
|
||||
<Loader2 className="w-4 h-4 animate-spin text-warning-600" />
|
||||
<div>
|
||||
<div className="text-sm font-medium text-foreground mb-1">
|
||||
Pipeline Failed - Loading logs...
|
||||
</div>
|
||||
<div className="text-xs text-foreground-light">
|
||||
Error logs are being retrieved from the container. This may take a few
|
||||
moments.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<span className="text-sm font-medium text-foreground">
|
||||
Pipeline Error Details
|
||||
</span>
|
||||
{(failedStatus.message || failedStatus.reason) && (
|
||||
<Button
|
||||
type="text"
|
||||
size="tiny"
|
||||
onClick={async () => {
|
||||
await handleCopyToClipboard(
|
||||
[
|
||||
failedStatus.exit_code !== undefined
|
||||
? `Exit Code: ${failedStatus.exit_code}`
|
||||
: null,
|
||||
failedStatus.reason ? `Reason: ${failedStatus.reason}` : null,
|
||||
failedStatus.message ? `Message: ${failedStatus.message}` : null,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n')
|
||||
)
|
||||
}}
|
||||
>
|
||||
<Copy className="w-3 h-3" />
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{failedStatus.exit_code !== undefined && (
|
||||
<div>
|
||||
<span className="text-xs font-medium text-foreground-light">
|
||||
Exit Code:
|
||||
</span>
|
||||
<div className="font-mono text-sm text-foreground mt-1">
|
||||
{failedStatus.exit_code}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{failedStatus.reason && (
|
||||
<div>
|
||||
<span className="text-xs font-medium text-foreground-light">Reason:</span>
|
||||
<pre className="font-mono text-sm text-foreground whitespace-pre-wrap break-words mt-1 max-h-32 overflow-y-auto">
|
||||
{failedStatus.reason}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
{failedStatus.message && (
|
||||
<div>
|
||||
<span className="text-xs font-medium text-foreground-light">
|
||||
Message:
|
||||
</span>
|
||||
<pre className="font-mono text-sm text-foreground whitespace-pre-wrap break-words mt-1 max-h-32 overflow-y-auto">
|
||||
{failedStatus.message}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
// Map backend statuses to UX-friendly display
|
||||
const getStatusConfig = () => {
|
||||
if (requestStatus === PipelineStatusRequestStatus.EnableRequested) {
|
||||
@@ -48,42 +241,59 @@ const PipelineStatus = ({
|
||||
}
|
||||
}
|
||||
|
||||
switch (pipelineStatus) {
|
||||
case 'Starting':
|
||||
return {
|
||||
label: 'Starting',
|
||||
dot: <Loader2 className="animate-spin w-3 h-3 text-warning-600" />,
|
||||
color: 'text-warning-600',
|
||||
tooltip: 'Pipeline is initializing and will be ready soon',
|
||||
}
|
||||
case 'Started':
|
||||
return {
|
||||
label: 'Running',
|
||||
dot: <div className="w-2 h-2 bg-brand-600 rounded-full" />,
|
||||
color: 'text-brand-600',
|
||||
tooltip: 'Pipeline is active and processing data',
|
||||
}
|
||||
case 'Stopped':
|
||||
return {
|
||||
label: 'Stopped',
|
||||
dot: <div className="w-2 h-2 bg-foreground-lighter rounded-full" />,
|
||||
color: 'text-foreground-light',
|
||||
tooltip: 'Pipeline is not running - enable to start processing',
|
||||
}
|
||||
case 'Unknown':
|
||||
return {
|
||||
label: 'Unknown',
|
||||
dot: <div className="w-2 h-2 bg-warning-600 rounded-full" />,
|
||||
color: 'text-warning-600',
|
||||
tooltip: 'Pipeline status could not be determined',
|
||||
}
|
||||
default:
|
||||
return {
|
||||
label: 'Unknown',
|
||||
dot: <div className="w-2 h-2 bg-destructive-600 rounded-full" />,
|
||||
color: 'text-destructive-600',
|
||||
tooltip: 'Pipeline status is unclear - check logs for details',
|
||||
}
|
||||
// Handle Failed status object
|
||||
if (isFailedStatus(pipelineStatus)) {
|
||||
return {
|
||||
isFailedStatus: true,
|
||||
}
|
||||
}
|
||||
|
||||
if (pipelineStatus && typeof pipelineStatus === 'object' && 'name' in pipelineStatus) {
|
||||
switch (pipelineStatus.name) {
|
||||
case PipelineStatusName.STARTING:
|
||||
return {
|
||||
label: 'Starting',
|
||||
dot: <Loader2 className="animate-spin w-3 h-3 text-warning-600" />,
|
||||
color: 'text-warning-600',
|
||||
tooltip: 'Pipeline is initializing and will be ready soon',
|
||||
}
|
||||
case PipelineStatusName.STARTED:
|
||||
return {
|
||||
label: 'Running',
|
||||
dot: <div className="w-2 h-2 bg-brand-600 rounded-full" />,
|
||||
color: 'text-brand-600',
|
||||
tooltip: 'Pipeline is active and processing data',
|
||||
}
|
||||
case PipelineStatusName.STOPPED:
|
||||
return {
|
||||
label: 'Stopped',
|
||||
dot: <div className="w-2 h-2 bg-foreground-lighter rounded-full" />,
|
||||
color: 'text-foreground-light',
|
||||
tooltip: 'Pipeline is not running - enable to start processing',
|
||||
}
|
||||
case PipelineStatusName.UNKNOWN:
|
||||
return {
|
||||
label: 'Unknown',
|
||||
dot: <div className="w-2 h-2 bg-warning-600 rounded-full" />,
|
||||
color: 'text-warning-600',
|
||||
tooltip: 'Pipeline status could not be determined',
|
||||
}
|
||||
default:
|
||||
return {
|
||||
label: 'Unknown',
|
||||
dot: <div className="w-2 h-2 bg-destructive-600 rounded-full" />,
|
||||
color: 'text-destructive-600',
|
||||
tooltip: 'Pipeline status is unclear - check logs for details',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for undefined or invalid status
|
||||
return {
|
||||
label: 'Unknown',
|
||||
dot: <div className="w-2 h-2 bg-destructive-600 rounded-full" />,
|
||||
color: 'text-destructive-600',
|
||||
tooltip: 'Pipeline status is unclear - check logs for details',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,19 +304,25 @@ const PipelineStatus = ({
|
||||
{isLoading && <ShimmeringLoader></ShimmeringLoader>}
|
||||
{isError && <AlertError error={error} subject="Failed to retrieve pipeline status" />}
|
||||
{isSuccess && (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div className={cn('flex items-center gap-2 text-sm', statusConfig.color)}>
|
||||
{statusConfig.dot}
|
||||
<span>{statusConfig.label}</span>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>{statusConfig.tooltip}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<>
|
||||
{statusConfig.isFailedStatus ? (
|
||||
<div className="relative">{renderFailedStatus(pipelineStatus as FailedStatus)}</div>
|
||||
) : (
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div className={cn('flex items-center gap-2 text-sm', statusConfig.color)}>
|
||||
{statusConfig.dot}
|
||||
<span>{statusConfig.label}</span>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>{statusConfig.tooltip}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -10,9 +10,10 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from 'ui'
|
||||
import ShimmeringLoader from 'ui-patterns/ShimmeringLoader'
|
||||
import { PipelineStatusName } from './PipelineStatus'
|
||||
|
||||
interface RowMenuProps {
|
||||
pipelineStatus: string | undefined
|
||||
pipelineStatus: any
|
||||
error: ResponseError | null
|
||||
isLoading: boolean
|
||||
isError: boolean
|
||||
@@ -32,7 +33,16 @@ const RowMenu = ({
|
||||
onEditClick,
|
||||
onDeleteClick,
|
||||
}: RowMenuProps) => {
|
||||
const pipelineEnabled = pipelineStatus === 'Stopped' ? false : true
|
||||
const getStatusName = (status: any) => {
|
||||
if (status && typeof status === 'object' && 'name' in status) {
|
||||
return status.name
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
const statusName = getStatusName(pipelineStatus)
|
||||
const pipelineEnabled = statusName !== PipelineStatusName.STOPPED
|
||||
|
||||
return (
|
||||
<div className="flex justify-end items-center space-x-2">
|
||||
{isLoading && <ShimmeringLoader></ShimmeringLoader>}
|
||||
|
||||
Vendored
+60
@@ -514,6 +514,26 @@ export interface paths {
|
||||
patch?: never
|
||||
trace?: never
|
||||
}
|
||||
'/v1/projects/{ref}/branches/{name}': {
|
||||
parameters: {
|
||||
query?: never
|
||||
header?: never
|
||||
path?: never
|
||||
cookie?: never
|
||||
}
|
||||
/**
|
||||
* Get a database branch
|
||||
* @description Fetches the specified database branch by its name.
|
||||
*/
|
||||
get: operations['v1-get-a-branch']
|
||||
put?: never
|
||||
post?: never
|
||||
delete?: never
|
||||
options?: never
|
||||
head?: never
|
||||
patch?: never
|
||||
trace?: never
|
||||
}
|
||||
'/v1/projects/{ref}/claim-token': {
|
||||
parameters: {
|
||||
query?: never
|
||||
@@ -3220,6 +3240,10 @@ export interface components {
|
||||
max_client_conn?: number
|
||||
/** @enum {string} */
|
||||
pool_mode?: 'transaction' | 'session' | 'statement'
|
||||
query_wait_timeout?: number
|
||||
reserve_pool_size?: number
|
||||
server_idle_timeout?: number
|
||||
server_lifetime?: number
|
||||
}
|
||||
V1PostgrestConfigResponse: {
|
||||
db_extra_search_path: string
|
||||
@@ -4633,6 +4657,42 @@ export interface operations {
|
||||
}
|
||||
}
|
||||
}
|
||||
'v1-get-a-branch': {
|
||||
parameters: {
|
||||
query?: never
|
||||
header?: never
|
||||
path: {
|
||||
name: string
|
||||
/** @description Project ref */
|
||||
ref: string
|
||||
}
|
||||
cookie?: never
|
||||
}
|
||||
requestBody?: never
|
||||
responses: {
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown
|
||||
}
|
||||
content: {
|
||||
'application/json': components['schemas']['BranchResponse']
|
||||
}
|
||||
}
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown
|
||||
}
|
||||
content?: never
|
||||
}
|
||||
/** @description Failed to fetch database branch */
|
||||
500: {
|
||||
headers: {
|
||||
[name: string]: unknown
|
||||
}
|
||||
content?: never
|
||||
}
|
||||
}
|
||||
}
|
||||
'v1-get-project-claim-token': {
|
||||
parameters: {
|
||||
query?: never
|
||||
|
||||
+64
-9
@@ -4896,7 +4896,7 @@ export interface components {
|
||||
id: string
|
||||
public: boolean
|
||||
/** @enum {string} */
|
||||
type?: 'STANDARD' | 'ICEBERG'
|
||||
type?: 'STANDARD' | 'ANALYTICS'
|
||||
}
|
||||
CreateStorageCredentialBody: {
|
||||
description: string
|
||||
@@ -6550,7 +6550,7 @@ export interface components {
|
||||
db_port: number
|
||||
db_user: string
|
||||
default_pool_size?: number
|
||||
ignore_startup_parameters: string
|
||||
ignore_startup_parameters?: string
|
||||
inserted_at: string
|
||||
max_client_conn?: number
|
||||
pgbouncer_enabled: boolean
|
||||
@@ -6558,6 +6558,10 @@ export interface components {
|
||||
pgbouncer_status: 'COMING_UP' | 'COMING_DOWN' | 'RELOADING' | 'ENABLED' | 'DISABLED'
|
||||
/** @enum {string} */
|
||||
pool_mode: 'transaction' | 'session' | 'statement'
|
||||
query_wait_timeout?: number
|
||||
reserve_pool_size?: number
|
||||
server_idle_timeout?: number
|
||||
server_lifetime?: number
|
||||
ssl_enforced: boolean
|
||||
}
|
||||
PgbouncerStatusResponse: {
|
||||
@@ -7281,6 +7285,14 @@ export interface components {
|
||||
}[]
|
||||
}
|
||||
}
|
||||
RemoveProjectResponse: {
|
||||
id: number
|
||||
name: string
|
||||
ref: string
|
||||
vercel?: {
|
||||
resourceUninstallFailure: boolean
|
||||
}
|
||||
}
|
||||
ReplicationDestinationResponse: {
|
||||
/** @description Destination config */
|
||||
config: {
|
||||
@@ -7385,11 +7397,38 @@ export interface components {
|
||||
tenant_id: string
|
||||
}[]
|
||||
}
|
||||
ReplicationPipelinesStatusResponse: {
|
||||
ReplicationPipelineStatusResponse: {
|
||||
/** @description Pipeline id */
|
||||
pipeline_id: number
|
||||
/** @description Pipeline status */
|
||||
status: string
|
||||
status:
|
||||
| {
|
||||
/** @enum {string} */
|
||||
name: 'stopped'
|
||||
}
|
||||
| {
|
||||
/** @enum {string} */
|
||||
name: 'starting'
|
||||
}
|
||||
| {
|
||||
/** @enum {string} */
|
||||
name: 'started'
|
||||
}
|
||||
| {
|
||||
/** @enum {string} */
|
||||
name: 'stopping'
|
||||
}
|
||||
| {
|
||||
/** @enum {string} */
|
||||
name: 'unknown'
|
||||
}
|
||||
| {
|
||||
exit_code?: number | null
|
||||
message?: string | null
|
||||
/** @enum {string} */
|
||||
name: 'failed'
|
||||
reason?: string | null
|
||||
}
|
||||
}
|
||||
ReplicationPublicationsResponse: {
|
||||
/** @description List of publications */
|
||||
@@ -7631,7 +7670,7 @@ export interface components {
|
||||
owner: string
|
||||
public: boolean
|
||||
/** @enum {string} */
|
||||
type?: 'STANDARD' | 'ICEBERG'
|
||||
type?: 'STANDARD' | 'ANALYTICS'
|
||||
updated_at: string
|
||||
}
|
||||
StorageConfigResponse: {
|
||||
@@ -7660,7 +7699,7 @@ export interface components {
|
||||
owner: string
|
||||
public: boolean
|
||||
/** @enum {string} */
|
||||
type?: 'STANDARD' | 'ICEBERG'
|
||||
type?: 'STANDARD' | 'ANALYTICS'
|
||||
updated_at: string
|
||||
}
|
||||
created_at: string
|
||||
@@ -8329,7 +8368,11 @@ export interface components {
|
||||
}
|
||||
UpdatePgbouncerConfigBody: {
|
||||
default_pool_size?: number
|
||||
ignore_startup_parameters: string
|
||||
/**
|
||||
* @deprecated
|
||||
* @default options,extra_float_digits
|
||||
*/
|
||||
ignore_startup_parameters?: string
|
||||
max_client_conn?: number
|
||||
/** @deprecated */
|
||||
pgbouncer_enabled?: boolean
|
||||
@@ -8338,6 +8381,10 @@ export interface components {
|
||||
* @enum {string}
|
||||
*/
|
||||
pool_mode?: 'transaction' | 'session' | 'statement'
|
||||
query_wait_timeout?: number
|
||||
reserve_pool_size?: number
|
||||
server_idle_timeout?: number
|
||||
server_lifetime?: number
|
||||
}
|
||||
UpdatePolicyBody: {
|
||||
check?: string
|
||||
@@ -8359,6 +8406,8 @@ export interface components {
|
||||
* @enum {string}
|
||||
*/
|
||||
pool_mode?: 'transaction' | 'session' | 'statement'
|
||||
server_idle_timeout?: number
|
||||
server_lifetime?: number
|
||||
}
|
||||
UpdatePostgresConfigBody: {
|
||||
effective_cache_size?: string
|
||||
@@ -14647,6 +14696,12 @@ export interface operations {
|
||||
'application/json': components['schemas']['ProjectDetailResponse']
|
||||
}
|
||||
}
|
||||
403: {
|
||||
headers: {
|
||||
[name: string]: unknown
|
||||
}
|
||||
content?: never
|
||||
}
|
||||
}
|
||||
}
|
||||
ProjectsRefController_deleteProject: {
|
||||
@@ -14666,7 +14721,7 @@ export interface operations {
|
||||
[name: string]: unknown
|
||||
}
|
||||
content: {
|
||||
'application/json': components['schemas']['ProjectRefResponse']
|
||||
'application/json': components['schemas']['RemoveProjectResponse']
|
||||
}
|
||||
}
|
||||
403: {
|
||||
@@ -18498,7 +18553,7 @@ export interface operations {
|
||||
[name: string]: unknown
|
||||
}
|
||||
content: {
|
||||
'application/json': components['schemas']['ReplicationPipelinesStatusResponse']
|
||||
'application/json': components['schemas']['ReplicationPipelineStatusResponse']
|
||||
}
|
||||
}
|
||||
403: {
|
||||
|
||||
Reference in new issue
Block a user