123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- import {
- topicsApiClient as api,
- messagesApiClient as messagesApi,
- consumerGroupsApiClient,
- messagesApiClient,
- } from 'lib/api';
- import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
- import {
- ClusterName,
- TopicFormData,
- TopicFormDataRaw,
- TopicFormFormattedParams,
- } from 'redux/interfaces';
- import {
- CreateTopicMessage,
- GetTopicDetailsRequest,
- GetTopicsRequest,
- Topic,
- TopicConfig,
- TopicCreation,
- TopicUpdate,
- } from 'generated-sources';
- import { showServerError, showSuccessAlert } from 'lib/errorHandling';
- export const topicKeys = {
- all: (clusterName: ClusterName) =>
- ['clusters', clusterName, 'topics'] as const,
- list: (
- clusterName: ClusterName,
- filters: Omit<GetTopicsRequest, 'clusterName'>
- ) => [...topicKeys.all(clusterName), filters] as const,
- details: ({ clusterName, topicName }: GetTopicDetailsRequest) =>
- [...topicKeys.all(clusterName), topicName] as const,
- config: (props: GetTopicDetailsRequest) =>
- [...topicKeys.details(props), 'config'] as const,
- schema: (props: GetTopicDetailsRequest) =>
- [...topicKeys.details(props), 'schema'] as const,
- consumerGroups: (props: GetTopicDetailsRequest) =>
- [...topicKeys.details(props), 'consumerGroups'] as const,
- statistics: (props: GetTopicDetailsRequest) =>
- [...topicKeys.details(props), 'statistics'] as const,
- };
- export function useTopics(props: GetTopicsRequest) {
- const { clusterName, ...filters } = props;
- return useQuery(
- topicKeys.list(clusterName, filters),
- () => api.getTopics(props),
- { keepPreviousData: true }
- );
- }
- export function useTopicDetails(props: GetTopicDetailsRequest) {
- return useQuery(topicKeys.details(props), () => api.getTopicDetails(props));
- }
- export function useTopicConfig(props: GetTopicDetailsRequest) {
- return useQuery(topicKeys.config(props), () => api.getTopicConfigs(props));
- }
- export function useTopicConsumerGroups(props: GetTopicDetailsRequest) {
- return useQuery(topicKeys.consumerGroups(props), () =>
- consumerGroupsApiClient.getTopicConsumerGroups(props)
- );
- }
- const topicReducer = (
- result: TopicFormFormattedParams,
- customParam: TopicConfig
- ) => {
- return {
- ...result,
- [customParam.name]: customParam.value,
- };
- };
- const formatTopicCreation = (form: TopicFormData): TopicCreation => {
- const {
- name,
- partitions,
- replicationFactor,
- cleanupPolicy,
- retentionMs,
- maxMessageBytes,
- minInSyncReplicas,
- customParams,
- } = form;
- const configs = {
- 'cleanup.policy': cleanupPolicy,
- 'retention.ms': retentionMs.toString(),
- 'max.message.bytes': maxMessageBytes.toString(),
- 'min.insync.replicas': minInSyncReplicas.toString(),
- ...Object.values(customParams || {}).reduce(topicReducer, {}),
- };
- const cleanConfigs = () => {
- return Object.fromEntries(
- Object.entries(configs).filter(([, val]) => val !== '')
- );
- };
- const topicsvalue = {
- name,
- partitions,
- configs: cleanConfigs(),
- };
- return replicationFactor.toString() !== ''
- ? {
- ...topicsvalue,
- replicationFactor,
- }
- : topicsvalue;
- };
- export function useCreateTopicMutation(clusterName: ClusterName) {
- const client = useQueryClient();
- return useMutation(
- (data: TopicFormData) =>
- api.createTopic({
- clusterName,
- topicCreation: formatTopicCreation(data),
- }),
- {
- onSuccess: () => {
- client.invalidateQueries(topicKeys.all(clusterName));
- },
- }
- );
- }
- // this will change later when we validate the request before
- export function useCreateTopic(clusterName: ClusterName) {
- const mutate = useCreateTopicMutation(clusterName);
- return {
- createResource: async (param: TopicFormData) => {
- return mutate.mutateAsync(param);
- },
- ...mutate,
- };
- }
- const formatTopicUpdate = (form: TopicFormDataRaw): TopicUpdate => {
- const {
- cleanupPolicy,
- retentionBytes,
- retentionMs,
- maxMessageBytes,
- minInSyncReplicas,
- customParams,
- } = form;
- return {
- configs: {
- ...Object.values(customParams || {}).reduce(topicReducer, {}),
- 'cleanup.policy': cleanupPolicy,
- 'retention.ms': retentionMs,
- 'retention.bytes': retentionBytes,
- 'max.message.bytes': maxMessageBytes,
- 'min.insync.replicas': minInSyncReplicas,
- },
- };
- };
- export function useUpdateTopic(props: GetTopicDetailsRequest) {
- const client = useQueryClient();
- return useMutation(
- (data: TopicFormDataRaw) => {
- return api.updateTopic({
- ...props,
- topicUpdate: formatTopicUpdate(data),
- });
- },
- {
- onSuccess: () => {
- showSuccessAlert({
- message: `Topic successfully updated.`,
- });
- client.invalidateQueries(topicKeys.all(props.clusterName));
- },
- }
- );
- }
- export function useIncreaseTopicPartitionsCount(props: GetTopicDetailsRequest) {
- const client = useQueryClient();
- return useMutation(
- (totalPartitionsCount: number) =>
- api.increaseTopicPartitions({
- ...props,
- partitionsIncrease: { totalPartitionsCount },
- }),
- {
- onSuccess: () => {
- showSuccessAlert({
- message: `Number of partitions successfully increased`,
- });
- client.invalidateQueries(topicKeys.all(props.clusterName));
- },
- }
- );
- }
- export function useUpdateTopicReplicationFactor(props: GetTopicDetailsRequest) {
- const client = useQueryClient();
- return useMutation(
- (totalReplicationFactor: number) =>
- api.changeReplicationFactor({
- ...props,
- replicationFactorChange: { totalReplicationFactor },
- }),
- {
- onSuccess: () => {
- showSuccessAlert({
- message: `Replication factor successfully updated`,
- });
- client.invalidateQueries(topicKeys.all(props.clusterName));
- },
- }
- );
- }
- export function useDeleteTopic(clusterName: ClusterName) {
- const client = useQueryClient();
- return useMutation(
- (topicName: Topic['name']) => api.deleteTopic({ clusterName, topicName }),
- {
- onSuccess: (_, topicName) => {
- showSuccessAlert({
- message: `Topic ${topicName} successfully deleted!`,
- });
- client.invalidateQueries(topicKeys.all(clusterName));
- },
- }
- );
- }
- export function useClearTopicMessages(
- clusterName: ClusterName,
- partitions?: number[]
- ) {
- const client = useQueryClient();
- return useMutation(
- async (topicName: Topic['name']) => {
- await messagesApiClient.deleteTopicMessages({
- clusterName,
- partitions,
- topicName,
- });
- return topicName;
- },
- {
- onSuccess: (topicName) => {
- showSuccessAlert({
- id: `message-${topicName}-${clusterName}-${partitions}`,
- message: `${topicName} messages have been successfully cleared!`,
- });
- client.invalidateQueries(topicKeys.all(clusterName));
- },
- }
- );
- }
- export function useRecreateTopic(props: GetTopicDetailsRequest) {
- const client = useQueryClient();
- return useMutation(() => api.recreateTopic(props), {
- onSuccess: () => {
- showSuccessAlert({
- message: `Topic ${props.topicName} successfully recreated!`,
- });
- client.invalidateQueries(topicKeys.all(props.clusterName));
- },
- });
- }
- export function useSendMessage(props: GetTopicDetailsRequest) {
- const client = useQueryClient();
- return useMutation(
- (message: CreateTopicMessage) =>
- messagesApi.sendTopicMessages({ ...props, createTopicMessage: message }),
- {
- onSuccess: () => {
- showSuccessAlert({
- message: `Message successfully sent`,
- });
- client.invalidateQueries(topicKeys.all(props.clusterName));
- },
- onError: (e) => {
- showServerError(e as Response);
- },
- }
- );
- }
- // Statistics
- export function useTopicAnalysis(
- props: GetTopicDetailsRequest,
- enabled = true
- ) {
- return useQuery(
- topicKeys.statistics(props),
- () => api.getTopicAnalysis(props),
- {
- enabled,
- refetchInterval: 1000,
- useErrorBoundary: true,
- retry: false,
- suspense: false,
- onError: (error: Response) => {
- if (error.status !== 404) {
- showServerError(error as Response);
- }
- },
- }
- );
- }
- export function useAnalyzeTopic(props: GetTopicDetailsRequest) {
- const client = useQueryClient();
- return useMutation(() => api.analyzeTopic(props), {
- onSuccess: () => {
- client.invalidateQueries(topicKeys.statistics(props));
- },
- });
- }
- export function useCancelTopicAnalysis(props: GetTopicDetailsRequest) {
- const client = useQueryClient();
- return useMutation(() => api.cancelTopicAnalysis(props), {
- onSuccess: () => {
- showSuccessAlert({
- message: `Topic analysis canceled`,
- });
- client.invalidateQueries(topicKeys.statistics(props));
- },
- });
- }
|