Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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