-
Notifications
You must be signed in to change notification settings - Fork 430
Remove topics from backend-api #2334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a961052
a48084a
7022209
dfb55a3
89885ca
4ee14d2
f8ba923
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,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'; | ||
|
|
@@ -87,7 +88,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 () => { | ||
|
|
@@ -478,7 +480,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 ( | ||
| <> | ||
|
|
@@ -536,13 +539,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> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we don't use the |
||
| 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() { | ||
|
|
@@ -553,9 +554,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} /> | ||
|
|
@@ -658,7 +656,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: [], | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,7 @@ import { | |
| import { StepSelectPartitions } from './step1-partitions'; | ||
| import { StepSelectBrokers } from './step2-brokers'; | ||
| import { StepReview, type TopicWithMoves } from './step3-review'; | ||
| import queryClient from '../../../query-client'; | ||
| import { appGlobal } from '../../../state/app-global'; | ||
| import { api, partialTopicConfigs } from '../../../state/backend-api'; | ||
| import type { | ||
|
|
@@ -185,8 +186,8 @@ class ReassignPartitions extends PageComponent { | |
|
|
||
| refreshData(force: boolean) { | ||
| api.refreshCluster(force); // need to know brokers for reassignment calculation, will also refresh config | ||
| api.refreshTopics(force); | ||
| api.refreshPartitions('all', force); | ||
| queryClient.invalidateQueries({ queryKey: ['topics'] }); | ||
| queryClient.invalidateQueries({ queryKey: ['topicPartitionsAll'] }); | ||
| api.refreshPartitionReassignments(force); | ||
| } | ||
|
|
||
|
|
@@ -200,16 +201,15 @@ class ReassignPartitions extends PageComponent { | |
| if (!api.clusterInfo) { | ||
| return DefaultSkeleton; | ||
| } | ||
| if (!api.topics) { | ||
| return DefaultSkeleton; | ||
| } | ||
|
|
||
| if (api.partitionReassignments === undefined) { | ||
| return DefaultSkeleton; | ||
| } | ||
|
|
||
| const partitionCountLeaders = api.topics?.sum((t) => t.partitionCount); | ||
| const partitionCountOnlyReplicated = api.topics?.sum((t) => t.partitionCount * (t.replicationFactor - 1)); | ||
| const cachedTopics = queryClient.getQueryData<import('../../../state/rest-interfaces').GetTopicsResponse>([ | ||
| 'topics', | ||
| ])?.topics; | ||
| const partitionCountLeaders = cachedTopics?.sum((t) => t.partitionCount); | ||
| const partitionCountOnlyReplicated = cachedTopics?.sum((t) => t.partitionCount * (t.replicationFactor - 1)); | ||
|
|
||
| const { currentStep, requestInProgress, partitionSelection, selectedBrokerIds, reassignmentRequest } = this.state; | ||
|
|
||
|
|
@@ -236,7 +236,10 @@ class ReassignPartitions extends PageComponent { | |
| <Statistic | ||
| title="Total Partitions" | ||
| value={ | ||
| partitionCountLeaders !== null && partitionCountOnlyReplicated !== null | ||
| partitionCountLeaders !== null && | ||
| partitionCountLeaders !== undefined && | ||
| partitionCountOnlyReplicated !== null && | ||
| partitionCountOnlyReplicated !== undefined | ||
| ? partitionCountLeaders + partitionCountOnlyReplicated | ||
| : '...' | ||
| } | ||
|
|
@@ -497,18 +500,24 @@ class ReassignPartitions extends PageComponent { | |
| } | ||
|
|
||
| const apiTopicPartitions = new Map<string, Partition[]>(); | ||
| for (const [topicName, partitions] of api.topicPartitions) { | ||
| const cachedTopicPartitions = queryClient.getQueryData< | ||
| Map<string, import('../../../state/rest-interfaces').Partition[] | null> | ||
| >(['topicPartitionsAll']); | ||
| for (const [topicName, partitions] of cachedTopicPartitions ?? | ||
| new Map<string, import('../../../state/rest-interfaces').Partition[] | null>()) { | ||
| if (!partitions) { | ||
| continue; | ||
| } | ||
| const validOnly = partitions.filter((x) => !x.hasErrors); | ||
| apiTopicPartitions.set(topicName, validOnly); | ||
| } | ||
|
|
||
| const cachedTopicsData = | ||
| queryClient.getQueryData<import('../../../state/rest-interfaces').GetTopicsResponse>(['topics'])?.topics ?? []; | ||
| // error checking will happen inside computeReassignments | ||
| const apiData: ApiData = { | ||
| brokers: api.clusterInfo?.brokers ?? [], | ||
| topics: api.topics as Topic[], | ||
| topics: cachedTopicsData as Topic[], | ||
| topicPartitions: apiTopicPartitions, | ||
| }; | ||
|
|
||
|
|
@@ -634,7 +643,10 @@ class ReassignPartitions extends PageComponent { | |
| const followerReplicas: { partitionId: number; brokerId: number }[] = []; | ||
| for (const p of t.partitions) { | ||
| const partitionId = p.partitionId; | ||
| const brokersOld = api.topicPartitions | ||
| const cachedTpForTraffic = queryClient.getQueryData< | ||
| Map<string, import('../../../state/rest-interfaces').Partition[] | null> | ||
| >(['topicPartitionsAll']); | ||
| const brokersOld = cachedTpForTraffic | ||
| ?.get(t.topicName) | ||
| ?.first((partition) => partition.id === partitionId)?.replicas; | ||
| const brokersNew = p.replicas; | ||
|
|
@@ -773,8 +785,12 @@ class ReassignPartitions extends PageComponent { | |
| } | ||
|
|
||
| get selectedTopicPartitions(): TopicPartitions[] | undefined { | ||
| const apiTopics = api.topics; | ||
| const apiPartitions = api.topicPartitions; | ||
| const apiTopics = queryClient.getQueryData<import('../../../state/rest-interfaces').GetTopicsResponse>([ | ||
| 'topics', | ||
| ])?.topics; | ||
| const apiPartitions = queryClient.getQueryData< | ||
| Map<string, import('../../../state/rest-interfaces').Partition[] | null> | ||
| >(['topicPartitionsAll']); | ||
|
|
||
| if (!(apiTopics && apiPartitions)) { | ||
| // biome-ignore lint/suspicious/useGetterReturn: early return for undefined case | ||
|
|
@@ -788,7 +804,10 @@ class ReassignPartitions extends PageComponent { | |
| let maxRf = 0; | ||
| for (const topicName in this.state.partitionSelection) { | ||
| if (Object.hasOwn(this.state.partitionSelection, topicName)) { | ||
| const topic = api.topics?.first((x) => x.topicName === topicName); | ||
| const cachedTopicsForRf = queryClient.getQueryData<import('../../../state/rest-interfaces').GetTopicsResponse>([ | ||
| 'topics', | ||
| ])?.topics; | ||
| const topic = cachedTopicsForRf?.first((x) => x.topicName === topicName); | ||
| if (topic && topic.replicationFactor > maxRf) { | ||
| maxRf = topic.replicationFactor; | ||
| } | ||
|
|
@@ -801,14 +820,21 @@ class ReassignPartitions extends PageComponent { | |
| if (this.state.reassignmentRequest === null) { | ||
| return []; | ||
| } | ||
| if (api.topics === null) { | ||
| const cachedTopicsForMoves = queryClient.getQueryData<import('../../../state/rest-interfaces').GetTopicsResponse>([ | ||
| 'topics', | ||
| ])?.topics; | ||
| if (!cachedTopicsForMoves) { | ||
| return []; | ||
| } | ||
| const cachedTpForMoves = | ||
| queryClient.getQueryData<Map<string, import('../../../state/rest-interfaces').Partition[] | null>>([ | ||
| 'topicPartitionsAll', | ||
| ]) ?? new Map<string, import('../../../state/rest-interfaces').Partition[] | null>(); | ||
|
Comment on lines
+830
to
+832
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this type of dynamic import? I would just import it, I guess react doctor might complain about it being a barrel file of some sort? I think in this case it would make it worse to have this import everywhere, just hoist it to the top of the file. |
||
| return computeMovedReplicas( | ||
| this.state.partitionSelection, | ||
| this.state.reassignmentRequest, | ||
| api.topics, | ||
| api.topicPartitions | ||
| cachedTopicsForMoves, | ||
| cachedTpForMoves | ||
| ); | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
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
useQueryClienthook to grab the singleton instance too.