From 35fa4ed81c6a61d7a7490b82a4370ced4c5a592a Mon Sep 17 00:00:00 2001 From: Julin <142230457+c-julin@users.noreply.github.com> Date: Wed, 24 Jun 2026 14:32:30 +0100 Subject: [PATCH] fix(sql): show bridge badge for Iceberg-tiered topics before sync [UX-1330] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SQL editor's "Bridge query" badge was gated on the presence of an Iceberg lag metric series rather than on whether the queried topic is actually Iceberg-tiered. A freshly-tiered topic that hasn't started translating yet emits no `iceberg_topic_translation_lag` / `iceberg_topic_commit_lag` series, so `bridge` resolved to undefined and the query — every row served from the topic tail — looked like a plain query. Classify bridge-ness from the authoritative `redpanda.iceberg.mode` config (via useTopicIcebergQuery, already used by the catalog tree), independent of lag-metric availability. Lag values default to 0 when their series is absent; the lag timeline stays hidden until real lag appears, but the badge now shows for any tiered topic. --- .../components/pages/sql/sql-workspace.tsx | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/pages/sql/sql-workspace.tsx b/frontend/src/components/pages/sql/sql-workspace.tsx index 5428f149af..41cea8aec0 100644 --- a/frontend/src/components/pages/sql/sql-workspace.tsx +++ b/frontend/src/components/pages/sql/sql-workspace.tsx @@ -33,6 +33,7 @@ import { useInvalidateSqlCatalog, useListCatalogsQuery, useListTablesQuery, + useTopicIcebergQuery, } from 'react-query/api/sql'; import { useLegacyListTopicsQuery } from 'react-query/api/topic'; import { toast } from 'sonner'; @@ -405,9 +406,17 @@ export function SqlWorkspace({ sqlRole: sqlRoleProp }: SqlWorkspaceProps) { })); }, [catalogsData]); + // Whether the queried topic is Iceberg-tiered — the authoritative bridge-query + // signal (`redpanda.iceberg.mode`), independent of any lag metric. A topic that + // is tiered but hasn't started translating yet emits no lag series, so the badge + // must key off the config, not metric presence (else a not-yet-synced bridge + // query — every row served from the topic — would look like a plain query). + const { isIceberg: bridgeTopicTiered } = useTopicIcebergQuery(bridgeTopic ?? '', { + enabled: Boolean(bridgeTopic), + }); // Bridge-query lag for the queried topic, read from the ObservabilityService - // (per-topic named queries) — decoupled from ExecuteQuery. A non-Iceberg topic - // has no pending-lag series, so `bridge` resolves to undefined and nothing shows. + // (per-topic named queries) — decoupled from ExecuteQuery. Drives only the lag + // timeline; the badge itself comes from `bridgeTopicTiered` above. const bridgeTxLag = useExecuteInstantQuery( { queryName: 'iceberg_topic_translation_lag', @@ -429,18 +438,18 @@ export function SqlWorkspace({ sqlRole: sqlRoleProp }: SqlWorkspaceProps) { { enabled: Boolean(bridgeTopic) } ); const bridge = useMemo(() => { - if (!bridgeTopic) { + // Bridge-ness is the topic being Iceberg-tiered — not whether lag has shown up. + // Lag defaults to 0 when its series is absent (e.g. translation hasn't started), + // which the timeline reads as "fully caught up" and hides; the badge still shows. + if (!(bridgeTopic && bridgeTopicTiered)) { return; } const tx = bridgeTxLag.data?.results?.[0]?.value?.value; const commit = bridgeCommitLag.data?.results?.[0]?.value?.value; - if (tx === undefined && commit === undefined) { - return; - } const translationLag = tx ?? 0; const commitLag = commit ?? 0; return { topic: bridgeTopic, translationLag, commitLag, totalLag: translationLag + commitLag }; - }, [bridgeTopic, bridgeTxLag.data, bridgeCommitLag.data]); + }, [bridgeTopic, bridgeTopicTiered, bridgeTxLag.data, bridgeCommitLag.data]); // Redpanda-catalog tables, fetched up front so both the add-topic wizard and // editor autocomplete (and the bridge indicator below) can resolve table refs.