mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
Local only: skip loading destinations if ETL API is not set up (#47031)
## Context > [!IMPORTANT] > Changes in this PR only apply to the local environment - there should not be any changes to staging (nor production) Given that read replicas currently sit under database replication, the UI currently waits for replication destinations to load before rendering the page. However for local development, setting up of the ETL API isn't necessary nor applicable for everyone so this indirectly adds friction if we just want to work with read replicas. ## Changes involved - Opting to skip retrying fetching ETL related requests if the error returned is "replication API URL is not configured" - This is indicative that the local platform isn't set up for ETL yet - ^ Database replication page will hence not wait for ETL requests to succeed before finally rendering the UI - Node diagram will also then render properly (just read replicas) - Add a small admonition to visualize this <img width="1079" height="301" alt="image" src="https://github.com/user-attachments/assets/32bd5d2f-a76e-417e-bedf-9a04de3bb305" /> ## To test - Will only be able to test locally - basically just head over to the database replication page (unless you somehow already have ETL API set up locally) - But can also verify that there's no changes on staging preview <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved error messaging when ETL is not configured in local development environments * Enhanced error handling for replication API failures with better non-retryable error detection * **Improvements** * Refined replication diagram rendering based on destination setup state * Updated dropdown menu interactions for read replica management <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
43e7ca65e0
commit
ea909e998b
3 files changed
+44
-6
No files matched your search
@@ -19,7 +19,7 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from 'ui'
|
||||
import { GenericSkeletonLoader } from 'ui-patterns'
|
||||
import { Admonition, GenericSkeletonLoader } from 'ui-patterns'
|
||||
import { Input } from 'ui-patterns/DataInputs/Input'
|
||||
|
||||
import { REPLICA_STATUS } from '../../Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants'
|
||||
@@ -43,6 +43,7 @@ import { replicationKeys } from '@/data/replication/keys'
|
||||
import { fetchReplicationPipelineVersion } from '@/data/replication/pipeline-version-query'
|
||||
import { useReplicationPipelinesQuery } from '@/data/replication/pipelines-query'
|
||||
import { useReplicationSourcesQuery } from '@/data/replication/sources-query'
|
||||
import { checkLocalETLNotSetUp } from '@/data/replication/utils'
|
||||
import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
|
||||
import { DOCS_URL } from '@/lib/constants'
|
||||
import { SHORTCUT_IDS } from '@/state/shortcuts/registry'
|
||||
@@ -144,7 +145,9 @@ export const Destinations = () => {
|
||||
pipelines.length === 0
|
||||
|
||||
const isLoading = isDestinationsLoading || isDatabasesLoading
|
||||
const hasErrorsFetchingData = isDestinationsError || isDatabasesError
|
||||
|
||||
const isLocalETLNotSetUp = checkLocalETLNotSetUp(destinationsError)
|
||||
const hasErrorsFetchingData = (!isLocalETLNotSetUp && isDestinationsError) || isDatabasesError
|
||||
|
||||
const openDestinationPanel = () => {
|
||||
if (!newDestinationDefaultType) return
|
||||
@@ -270,6 +273,13 @@ export const Destinations = () => {
|
||||
/>
|
||||
)}
|
||||
|
||||
{isLocalETLNotSetUp && (
|
||||
<Admonition
|
||||
type="default"
|
||||
title="ETL API not set up locally — destinations cannot be managed"
|
||||
/>
|
||||
)}
|
||||
|
||||
{isLoading ? (
|
||||
<GenericSkeletonLoader />
|
||||
) : hasReplicas || hasDestinations ? (
|
||||
|
||||
+15
-3
@@ -12,6 +12,7 @@ import { timeout } from '@/lib/helpers'
|
||||
import '@xyflow/react/dist/style.css'
|
||||
|
||||
import { SmoothstepEdge } from './Edges'
|
||||
import { checkLocalETLNotSetUp } from '@/data/replication/utils'
|
||||
|
||||
export const ReplicationDiagram = () => {
|
||||
return (
|
||||
@@ -42,10 +43,17 @@ const ReplicationDiagramContent = () => {
|
||||
[databases, projectRef]
|
||||
)
|
||||
|
||||
const { data, isSuccess: isSuccessDestinations } = useReplicationDestinationsQuery({
|
||||
const {
|
||||
data,
|
||||
error: destinationsError,
|
||||
isSuccess: isSuccessDestinations,
|
||||
isError: isErrorDestinations,
|
||||
} = useReplicationDestinationsQuery({
|
||||
projectRef,
|
||||
})
|
||||
const destinations = useMemo(() => data?.destinations ?? [], [data])
|
||||
const isLocalETLNotSetUp = checkLocalETLNotSetUp(destinationsError)
|
||||
const skipRenderingDestinations = isErrorDestinations && isLocalETLNotSetUp
|
||||
|
||||
const nodes = useMemo(() => {
|
||||
return [
|
||||
@@ -103,10 +111,14 @@ const ReplicationDiagramContent = () => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (nodes.length > 0 && isSuccessDestinations && isSuccessReplicas) {
|
||||
if (
|
||||
nodes.length > 0 &&
|
||||
(isSuccessDestinations || skipRenderingDestinations) &&
|
||||
isSuccessReplicas
|
||||
) {
|
||||
setReactFlow()
|
||||
}
|
||||
}, [nodes, isSuccessDestinations, isSuccessReplicas])
|
||||
}, [nodes, isSuccessDestinations, skipRenderingDestinations, isSuccessReplicas])
|
||||
|
||||
return (
|
||||
<div className="nowheel relative min-h-[350px]">
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
import { MAX_RETRY_FAILURE_COUNT } from '@/data/query-client'
|
||||
import { ResponseError } from '@/types'
|
||||
|
||||
const isLocal =
|
||||
process.env.NEXT_PUBLIC_ENVIRONMENT !== 'prod' &&
|
||||
process.env.NEXT_PUBLIC_ENVIRONMENT !== 'staging'
|
||||
|
||||
export const checkLocalETLNotSetUp = (error: ResponseError | null) => {
|
||||
if (error === null) return false
|
||||
|
||||
const isETLAPINotRunning =
|
||||
error.code === undefined && error.message.includes('API error happened')
|
||||
const isETLNotSetUp =
|
||||
error.code === 503 && error.message.includes('replication API URL is not configured')
|
||||
return isLocal && (isETLAPINotRunning || isETLNotSetUp)
|
||||
}
|
||||
|
||||
export const checkReplicationFeatureFlagRetry = (
|
||||
failureCount: number,
|
||||
error: ResponseError
|
||||
@@ -10,7 +24,9 @@ export const checkReplicationFeatureFlagRetry = (
|
||||
error.code === 503 &&
|
||||
error.message.includes('feature flag is required')
|
||||
|
||||
if (isFeatureFlagRequiredError) {
|
||||
const isLocalETLNotSetUp = checkLocalETLNotSetUp(error)
|
||||
|
||||
if (isFeatureFlagRequiredError || isLocalETLNotSetUp) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user