mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 17:35:10 +03:00
fix(studio): Handle query timeout error (#34865)
* fix(studio): Handle query timeout error There is a global timeout of about 50s on /query endpoint This would fail the request independently from the user statement timeout setting add a case to handle this error and add a CTA to suggest the user of direct connection for long running queries * chore: apply pr comments * Tiny refactor --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
This commit is contained in:
1 parent
8b55ffe2d8
commit
4a3baa6ab6
2 files changed
+31
-30
No files matched your search
@@ -1,15 +1,16 @@
|
||||
import { ExternalLink, Loader2 } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { parseAsBoolean, useQueryState } from 'nuqs'
|
||||
import { forwardRef } from 'react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { subscriptionHasHipaaAddon } from 'components/interfaces/Billing/Subscription/Subscription.utils'
|
||||
import CopyButton from 'components/ui/CopyButton'
|
||||
import { InlineLink, InlineLinkClassName } from 'components/ui/InlineLink'
|
||||
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
|
||||
import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
|
||||
import { useDatabaseSelectorStateSnapshot } from 'state/database-selector'
|
||||
import { useSqlEditorV2StateSnapshot } from 'state/sql-editor-v2'
|
||||
import { AiIconAnimation, Button, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
||||
import { AiIconAnimation, Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'
|
||||
import Results from './Results'
|
||||
|
||||
export type UtilityTabResultsProps = {
|
||||
@@ -21,11 +22,12 @@ export type UtilityTabResultsProps = {
|
||||
}
|
||||
|
||||
const UtilityTabResults = forwardRef<HTMLDivElement, UtilityTabResultsProps>(
|
||||
({ id, isExecuting, isDisabled, isDebugging, onDebug }, htmlRef) => {
|
||||
({ id, isExecuting, isDisabled, isDebugging, onDebug }) => {
|
||||
const { ref } = useParams()
|
||||
const state = useDatabaseSelectorStateSnapshot()
|
||||
const organization = useSelectedOrganization()
|
||||
const snapV2 = useSqlEditorV2StateSnapshot()
|
||||
const [, setShowConnect] = useQueryState('showConnect', parseAsBoolean.withDefault(false))
|
||||
|
||||
const result = snapV2.results[id]?.[0]
|
||||
const { data: subscription } = useOrgSubscriptionQuery({ orgSlug: organization?.slug })
|
||||
@@ -35,7 +37,9 @@ const UtilityTabResults = forwardRef<HTMLDivElement, UtilityTabResultsProps>(
|
||||
|
||||
const isTimeout =
|
||||
result?.error?.message?.includes('canceling statement due to statement timeout') ||
|
||||
result?.error?.message?.includes('upstream request timeout')
|
||||
result?.error?.message?.includes('upstream request timeout') ||
|
||||
result?.error?.message?.includes('Query read timeout')
|
||||
|
||||
const isNetWorkError = result?.error?.message?.includes('EHOSTUNREACH')
|
||||
|
||||
if (isExecuting) {
|
||||
@@ -61,26 +65,25 @@ const UtilityTabResults = forwardRef<HTMLDivElement, UtilityTabResultsProps>(
|
||||
<div className="flex flex-row justify-between items-start py-4 px-6 gap-x-4">
|
||||
{isTimeout ? (
|
||||
<div className="flex flex-col gap-y-1">
|
||||
<p className="font-mono text-sm">SQL query ran into an upstream timeout</p>
|
||||
<p className="font-mono text-sm text-foreground-light">
|
||||
<p className="font-mono text-sm tracking-tight">
|
||||
Error: SQL query ran into an upstream timeout
|
||||
</p>
|
||||
<p className="text-sm text-foreground-light">
|
||||
You can either{' '}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="underline transition hover:text-foreground"
|
||||
href="https://supabase.com/docs/guides/platform/performance#examining-query-performance"
|
||||
>
|
||||
<InlineLink href="https://supabase.com/docs/guides/platform/performance#examining-query-performance">
|
||||
optimize your query
|
||||
</a>
|
||||
</InlineLink>
|
||||
, or{' '}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="underline transition hover:text-foreground"
|
||||
href="https://supabase.com/docs/guides/database/timeouts"
|
||||
>
|
||||
<InlineLink href="https://supabase.com/docs/guides/database/timeouts">
|
||||
increase the statement timeout
|
||||
</a>
|
||||
</InlineLink>
|
||||
{' or '}
|
||||
<span
|
||||
className={cn(InlineLinkClassName, 'cursor-pointer')}
|
||||
onClick={() => setShowConnect(true)}
|
||||
>
|
||||
connect to your database directly
|
||||
</span>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
@@ -110,15 +113,13 @@ const UtilityTabResults = forwardRef<HTMLDivElement, UtilityTabResultsProps>(
|
||||
{payloadTooLargeError && (
|
||||
<p className="text-sm text-foreground-light flex items-center gap-x-1">
|
||||
Run this query by{' '}
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
href={`/project/${ref}/settings/database`}
|
||||
className="underline transition hover:text-foreground flex items-center gap-x-1"
|
||||
<span
|
||||
onClick={() => setShowConnect(true)}
|
||||
className={cn(InlineLinkClassName, 'flex items-center gap-x-1')}
|
||||
>
|
||||
connecting to your database directly
|
||||
<ExternalLink size={12} />
|
||||
</Link>
|
||||
</span>
|
||||
.
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -9,16 +9,16 @@ interface InlineLinkProps {
|
||||
rel?: string
|
||||
}
|
||||
|
||||
export const InlineLinkClassName =
|
||||
'underline transition underline-offset-2 decoration-foreground-lighter hover:decoration-foreground text-foreground'
|
||||
|
||||
export const InlineLink = ({
|
||||
href,
|
||||
className: _className,
|
||||
children,
|
||||
...props
|
||||
}: PropsWithChildren<InlineLinkProps>) => {
|
||||
const className = cn(
|
||||
'underline transition underline-offset-2 decoration-foreground-lighter hover:decoration-foreground text-foreground',
|
||||
_className
|
||||
)
|
||||
const className = cn(InlineLinkClassName, _className)
|
||||
if (href.startsWith('http')) {
|
||||
return (
|
||||
<a className={className} href={href} target="_blank" rel="noreferrer noopener" {...props}>
|
||||
|
||||
Reference in new issue
Block a user