Skip to content
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions frontend/src/components/pages/admin/admin-debug-bundle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
type SCRAMAuth,
SCRAMAuth_Mechanism,
} from '../../../protogen/redpanda/api/console/v1alpha1/debug_bundle_pb';
import queryClient from '../../../query-client';
import { appGlobal } from '../../../state/app-global';
import { api, useApiStoreHook } from '../../../state/backend-api';
import type { BrokerWithConfigAndStorage } from '../../../state/rest-interfaces';
Expand Down Expand Up @@ -216,9 +217,7 @@ const NewDebugBundleForm: FC<{

useEffect(() => {
api.refreshBrokers(true);
api.refreshPartitions('all', true).catch(() => {
// Error handling managed by API layer
});
queryClient.invalidateQueries({ queryKey: ['topicPartitionsAll'] });
Copy link
Copy Markdown
Contributor

@malinskibeniamin malinskibeniamin Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can rely on a useQueryClient hook to grab the singleton instance too.

}, []);

const fieldViolationsMap = error?.details
Expand Down
19 changes: 9 additions & 10 deletions frontend/src/components/pages/connect/connector-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import React, { useEffect, useRef, useState } from 'react';

import { ConfigPage } from './dynamic-ui/components';
import { useTopicsQuery } from '../../../react-query/api/topic';
import { appGlobal } from '../../../state/app-global';
import { api, createMessageSearch, type MessageSearch, type MessageSearchRequest } from '../../../state/backend-api';
import { ConnectClusterStore } from '../../../state/connect/state';
Expand Down Expand Up @@ -89,7 +90,8 @@ const KafkaConnectorMain = ({
}) => {
const [connectClusterStore] = useState(() => ConnectClusterStore.getInstance(clusterName));

const logsTopic = api.topics?.first((x) => x.topicName === LOGS_TOPIC_NAME);
const { data: topicsData } = useTopicsQuery();
const logsTopic = topicsData?.topics?.first((x) => x.topicName === LOGS_TOPIC_NAME);

useEffect(() => {
const init = async () => {
Expand Down Expand Up @@ -494,7 +496,8 @@ const ConnectorErrorModal = (p: { error: ConnectorError }) => {

const errorType = p.error.type === 'ERROR' ? 'error' : 'warning';

const hasConnectorLogs = api.topics?.any((x) => x.topicName === LOGS_TOPIC_NAME);
const { data: connectorTopicsData } = useTopicsQuery();
const hasConnectorLogs = connectorTopicsData?.topics?.any((x) => x.topicName === LOGS_TOPIC_NAME);

return (
<>
Expand Down Expand Up @@ -552,13 +555,11 @@ class KafkaConnectorDetails extends PageComponent<{ clusterName: string; connect
appGlobal.onRefresh = () => this.refreshData(true).catch(console.error);
}

async refreshData(force: boolean): Promise<void> {
async refreshData(_force: boolean): Promise<void> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't use the _force, should we drop it

ConnectClusterStore.connectClusters.clear();
await api.refreshConnectClusters();

// refresh topics so we know whether or not we can show the "go to error logs topic" button in the connector details error popup
// and show the logs tab
api.refreshTopics(force);
// React Query handles topics fetching via useTopicsQuery hooks in child components
}

render() {
Expand All @@ -569,9 +570,6 @@ class KafkaConnectorDetails extends PageComponent<{ clusterName: string; connect
return <NotConfigured />;
}

// Touch observables so PageComponent's Reaction tracks them for re-renders.
void api.topics;

return (
<PageContent>
<KafkaConnectorMain clusterName={clusterName} connectorName={connectorName} refreshData={this.refreshData} />
Expand Down Expand Up @@ -674,7 +672,8 @@ const LogsTab = (p: {
const { connector } = p;
const connectorName = connector.name;
const topicName = LOGS_TOPIC_NAME;
const topic = api.topics?.first((x) => x.topicName === topicName);
const { data: logsTopicsData } = useTopicsQuery();
const topic = logsTopicsData?.topics?.first((x) => x.topicName === topicName);

const [logState, setLogState] = useState<{ messages: TopicMessage[]; isComplete: boolean }>({
messages: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ import {
isMultiValue,
Select,
} from '@redpanda-data/ui';
import { useEffect, useMemo, useState } from 'react';
import { useMemo, useState } from 'react';

import { api } from '../../../../../state/backend-api';
import { useTopicsQuery } from '../../../../../react-query/api/topic';
import type { Property } from '../../../../../state/connect/state';
import { ExpandableText } from '../../../../misc/expandable-text';

Expand All @@ -40,9 +40,7 @@ export const TopicInput = (p: { properties: Property[]; connectorType: 'sink' |

const [selected, setSelected] = useState(initialSelection);

useEffect(() => {
api.refreshTopics();
}, []);
const { data: topicsData } = useTopicsQuery();

const property = propsMap.get(selected);
const isRegex = selected === 'topics.regex';
Expand Down Expand Up @@ -97,7 +95,7 @@ export const TopicInput = (p: { properties: Property[]; connectorType: 'sink' |
setPropertyValue(property, v.map(({ value }) => value)?.join(',') ?? []);
}
}}
options={api.topics?.map((x) => ({ value: x.topicName, label: x.topicName })) ?? []}
options={topicsData?.topics?.map((x) => ({ value: x.topicName, label: x.topicName })) ?? []}
value={
property.value
? property.value
Expand Down
19 changes: 13 additions & 6 deletions frontend/src/components/pages/consumers/modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import {
import { ChevronLeftIcon, ChevronRightIcon, SkipIcon, TrashIcon, WarningIcon } from 'components/icons';
import { Component } from 'react';

import queryClient from '../../../query-client';
import { getTopicOffsetsByTimestamp } from '../../../react-query/api/topic';
import { appGlobal } from '../../../state/app-global';
import { api } from '../../../state/backend-api';
import type {
Expand Down Expand Up @@ -496,7 +498,7 @@ export class EditOffsetsModal extends Component<{

let offsetsForTimestamp: TopicOffset[];
try {
offsetsForTimestamp = await api.getTopicOffsetsByTimestamp(requiredTopics, this.state.timestampUtcMs);
offsetsForTimestamp = await getTopicOffsetsByTimestamp(requiredTopics, this.state.timestampUtcMs);
toast.update(toastRef, {
status: 'success',
duration: 2000,
Expand Down Expand Up @@ -658,10 +660,9 @@ export class EditOffsetsModal extends Component<{
// need all groups for "other groups" dropdown
api.refreshConsumerGroups();

// need watermarks for all topics the group consumes
// in order to know earliest/latest offsets
// React Query handles partition data; invalidate to force refetch
const topics = this.props.group.topicOffsets.map((x) => x.topic).distinct();
api.refreshPartitions(topics, true);
queryClient.invalidateQueries({ queryKey: ['topicPartitionsAll', ...topics.slice().sort()] });

// reset settings
this.setState({ page: 0, selectedOption: 'startOffset' });
Expand Down Expand Up @@ -785,7 +786,10 @@ class ColAfter extends Component<{

// not found - no message after given timestamp
// use 'latest'
const partition = api.topicPartitions.get(record.topicName)?.first((p) => p.id === record.partitionId);
const partitionsAllData = queryClient.getQueryData<
Map<string, import('../../../state/rest-interfaces').Partition[] | null>
>(['topicPartitionsAll']);
const partition = partitionsAllData?.get(record.topicName)?.first((p) => p.id === record.partitionId);
return (
<div style={{ display: 'inline-flex', gap: '6px', alignItems: 'center' }}>
<InfoText
Expand Down Expand Up @@ -816,7 +820,10 @@ class ColAfter extends Component<{
}

// Get offset from current partition values
const partition = api.topicPartitions.get(record.topicName)?.first((p) => p.id === record.partitionId);
const partitionsAllData2 = queryClient.getQueryData<
Map<string, import('../../../state/rest-interfaces').Partition[] | null>
>(['topicPartitionsAll']);
const partition = partitionsAllData2?.get(record.topicName)?.first((p) => p.id === record.partitionId);

const content =
val === -2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
import React, { Component, type FC, useRef, useState } from 'react';

import { BandwidthSlider } from './bandwidth-slider';
import queryClient from '../../../../query-client';
import { api } from '../../../../state/backend-api';
import type { ConfigEntry } from '../../../../state/rest-interfaces';
import { QuickTable } from '../../../../utils/tsx-utils';
Expand Down Expand Up @@ -376,19 +377,17 @@ export class ReassignmentDetailsDialog extends Component<{ state: ReassignmentSt
// became visible or invisible
// force update of topic config, so isThrottle has up to date information
setTimeout(async () => {
api.topicConfig.delete(state.topicName);
await api.refreshTopicConfig(state.topicName, true);
await queryClient.invalidateQueries({ queryKey: ['topicConfig', state.topicName] });
this.setState({ shouldThrottle: this.isThrottled() });
});
}
this.wasVisible = visible;

const topicConfig = api.topicConfig.get(state.topicName);
if (!topicConfig) {
setTimeout(() => {
api.refreshTopicConfig(state.topicName);
});
}
const topicConfig =
queryClient.getQueryData<import('../../../../state/rest-interfaces').TopicDescription | null>([
'topicConfig',
state.topicName,
]) ?? null;

const replicas = state.partitions.flatMap((p) => p.replicas).distinct();
const addingReplicas = state.partitions.flatMap((p) => p.addingReplicas).distinct();
Expand Down Expand Up @@ -463,7 +462,11 @@ export class ReassignmentDetailsDialog extends Component<{ state: ReassignmentSt
if (!this.lastState) {
return false;
}
const config = api.topicConfig.get(this.lastState.topicName);
const config =
queryClient.getQueryData<import('../../../../state/rest-interfaces').TopicDescription | null>([
'topicConfig',
this.lastState.topicName,
]) ?? null;
if (!config) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@
* by the Apache License, Version 2.0
*/

import queryClient from '../../../../query-client';
import { api } from '../../../../state/backend-api';
import type { Broker, Partition } from '../../../../state/rest-interfaces';
import { prettyBytesOrNA } from '../../../../utils/utils';
import type { PartitionSelection } from '../reassign-partitions';

export function SelectionInfoBar(props: { partitionSelection: PartitionSelection; margin?: string }) {
if (api.topicPartitions === null) {
const topicPartitionsAll = queryClient.getQueryData<Map<string, Partition[] | null>>(['topicPartitionsAll']);
if (topicPartitionsAll === null) {
return null;
}

const selectedPartitions: { topic: string; partitions: Partition[] }[] = [];
for (const [topic, partitions] of api.topicPartitions) {
for (const [topic, partitions] of topicPartitionsAll ?? new Map<string, Partition[] | null>()) {
if (partitions === null) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// - manages timers for refreshing current reassignments
// - tracks progress history for each reassignment to estimate speed and ETA

import queryClient from '../../../../query-client';
import { api } from '../../../../state/backend-api';
import type { PartitionReassignments } from '../../../../state/rest-interfaces';
import { IsDev } from '../../../../utils/env';
Expand Down Expand Up @@ -114,7 +115,7 @@ export class ReassignmentTracker {
// Update relevant topic-partitions
const topics = liveReassignments.map((r) => r.topicName);
if (topics.length > 0) {
await api.refreshPartitions(topics, true);
queryClient.invalidateQueries({ queryKey: ['topicPartitionsAll'] });
}

// Add new reassignments
Expand Down Expand Up @@ -189,7 +190,10 @@ export class ReassignmentTracker {
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: legacy code
updateReassignmentState(state: ReassignmentState) {
// partition stats
const topicPartitions = api.topicPartitions.get(state.topicName);
const topicPartitionsAllData = queryClient.getQueryData<
Map<string, import('../../../../state/rest-interfaces').Partition[] | null>
>(['topicPartitionsAll']);
const topicPartitions = topicPartitionsAllData?.get(state.topicName);
for (const p of state.partitions) {
const logDirs = topicPartitions?.first((e) => e.id === p.partitionId)?.partitionLogDirs.filter((l) => !l.error);
if (!logDirs || logDirs.length === 0) {
Expand Down
Loading
Loading