Skip to content

Commit

Permalink
[PLAT-12554] Use DR api in Repair DR modal and drop table from DR mod…
Browse files Browse the repository at this point in the history
…al and allow empty dbs field for full restart

Summary:
In the repair DR config modal, the option to restart the current DR config sends a restart xCluster config request rather than a restart DR config request.
As we now have dedicated DR config APIs for restarting, this diff replaces the restart xCluster config request with a restart DR config request.
In the drop table modal for DR, we were using the xCluster edit table api instead of the set table api for DR. This diff addresses this by switching to the
DR api when the replication table component is used in DR context.

For the restart DR config request, we did not accept empty `dbs` fields prior to this change.
This means the client must make additional GET requests to map the DR config's table UUIDs to namespace UUIDs on the source universe.
When the only available option is a complete restart of the entire config, the additional network requests are unnecessary.
This diff removes the requirement of non-empty `dbs` field to make the restart DR config request consistent with the restart xCluster config request.
If the user provides an empty `dbs` field, then we will interpret it as a request to restart for all tables in the config.

Test Plan:
Verify that the the repair DR modal sends a restart DR config request.
Verify that a restart DR config request with an empty `dbs` field is not rejected.

Reviewers: cwang, hzare, sanketh

Reviewed By: cwang

Subscribers: yugaware

Differential Revision: https://phorge.dev.yugabyte.com/D32202
  • Loading branch information
Jethro-M committed Feb 6, 2024
1 parent 1d410d7 commit abcdf7c
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.yb.CommonTypes;
import org.yb.master.MasterDdlOuterClass;
Expand Down Expand Up @@ -381,9 +382,13 @@ public Result restart(
XClusterConfigTaskBase.getTableInfoList(ybService, sourceUniverse);

// Todo: Always add non existing tables to the xCluster config on restart.
// Empty `dbs` field indicates a request to restart the entire config.
// This is consistent with the restart xCluster config behaviour.
Set<String> tableIds =
XClusterConfigTaskBase.getTableIds(
getRequestedTableInfoList(restartForm.dbs, sourceTableInfoList));
CollectionUtils.isEmpty(restartForm.dbs)
? xClusterConfig.getTableIds()
: XClusterConfigTaskBase.getTableIds(
getRequestedTableInfoList(restartForm.dbs, sourceTableInfoList));

XClusterConfigTaskParams taskParams =
XClusterConfigController.getRestartTaskParams(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import java.util.Set;
import javax.validation.Valid;
import lombok.ToString;
import play.data.validation.Constraints.Required;

@ApiModel(description = "dr config restart form")
@ToString
Expand All @@ -16,7 +15,6 @@ public class DrConfigRestartForm {
value = "Primary Universe DB IDs",
example = "[\"0000412b000030008000000000000000\", \"0000412b000030008000000000000001\"]",
required = true)
@Required
public Set<String> dbs;

@Valid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,7 @@ export function ReplicationDetails({
<ReplicationTables
xClusterConfig={xClusterConfig}
isActive={window.location.search === '?tab=tables'}
isDrInterface={false}
/>
</Tab>
<Tab eventKey={'metrics'} title="Metrics" id="universe-tab-panel">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ import DeleteReplicactionTableModal from './DeleteReplicactionTableModal';
import { ReplicationLagGraphModal } from './ReplicationLagGraphModal';
import { YBLabelWithIcon } from '../../common/descriptors';
import ellipsisIcon from '../../common/media/more.svg';
import { api, universeQueryKey, xClusterQueryKey } from '../../../redesign/helpers/api';
import {
api,
drConfigQueryKey,
universeQueryKey,
xClusterQueryKey
} from '../../../redesign/helpers/api';
import {
XClusterModalName,
XClusterTableStatus,
Expand All @@ -48,22 +53,22 @@ import { XClusterConfig } from '../dtos';

import styles from './ReplicationTables.module.scss';

interface props {
interface CommonReplicationTablesProps {
xClusterConfig: XClusterConfig;

// isActive determines whether the component will make periodic
// queries for metrics.
isActive?: boolean;
isDrInterface?: boolean;
}

type ReplicationTablesProps =
| (CommonReplicationTablesProps & { isDrInterface: true; drConfigUuid: string })
| (CommonReplicationTablesProps & { isDrInterface: false });

const TABLE_MIN_PAGE_SIZE = 10;

export function ReplicationTables({
xClusterConfig,
isActive = true,
isDrInterface = false
}: props) {
export function ReplicationTables(props: ReplicationTablesProps) {
const { xClusterConfig, isActive = true } = props;
const [deleteTableDetails, setDeleteTableDetails] = useState<XClusterTable>();
const [openTableLagGraphDetails, setOpenTableLagGraphDetails] = useState<XClusterTable>();

Expand All @@ -87,31 +92,44 @@ export function ReplicationTables({

const removeTableFromXCluster = useMutation(
(replication: XClusterConfig) => {
return editXClusterConfigTables(replication.uuid, replication.tables);
return props.isDrInterface
? api.updateTablesInDr(props.drConfigUuid, { tables: replication.tables })
: editXClusterConfigTables(replication.uuid, replication.tables);
},
{
onSuccess: (response, xClusterConfig) => {
fetchTaskUntilItCompletes(response.taskUUID, (err: boolean) => {
if (!err) {
queryClient.invalidateQueries(xClusterQueryKey.detail(xClusterConfig.uuid));
if (props.isDrInterface) {
queryClient.invalidateQueries(drConfigQueryKey.detail(props.drConfigUuid));
toast.success(
deleteTableDetails
? `"${getTableName(deleteTableDetails)}" table removed successully.`
: 'Table removed successfully.'
);
} else {
toast.success(
deleteTableDetails
? `"${getTableName(deleteTableDetails)}" table removed successfully from ${
xClusterConfig.name
}.`
: `Table removed successfully from ${xClusterConfig.name}`
);
}
dispatch(closeDialog());
toast.success(
deleteTableDetails
? `"${getTableName(deleteTableDetails)}" table removed successfully from ${
xClusterConfig.name
}.`
: `Table removed successfully from ${xClusterConfig.name}`
);
} else {
toast.error(
<span className="alertMsg">
<i className="fa fa-exclamation-circle" />
<span>
{deleteTableDetails
? `Failed to remove table "${getTableName(deleteTableDetails)}" from ${
xClusterConfig.name
}.`
: `Failed to remove table from ${xClusterConfig.name}.`}
? `Failed to remove table "${getTableName(deleteTableDetails)}"${
props.isDrInterface ? '.' : ` from ${xClusterConfig.name}.`
}`
: `Failed to remove table${
props.isDrInterface ? '.' : ` from ${xClusterConfig.name}.`
}`}
</span>
<a href={`/tasks/${response.taskUUID}`} target="_blank" rel="noopener noreferrer">
View Details
Expand All @@ -122,7 +140,7 @@ export function ReplicationTables({
});
},
onError: (error: Error | AxiosError) => {
handleServerError(error, { customErrorLabel: 'Create xCluster config request failed' });
handleServerError(error, { customErrorLabel: 'Remove table request failed' });
}
}
);
Expand Down Expand Up @@ -155,7 +173,7 @@ export function ReplicationTables({
showModal && visibleModal === XClusterModalName.ADD_TABLE_TO_CONFIG;
return (
<div className={styles.rootContainer}>
{!isDrInterface && (
{!props.isDrInterface && (
<div className={styles.headerSection}>
<span className={styles.infoText}>Tables selected for Replication</span>
<div className={styles.actionBar}>
Expand Down Expand Up @@ -205,7 +223,7 @@ export function ReplicationTables({
>
Schema Name
</TableHeaderColumn>
{!isDrInterface && (
{!props.isDrInterface && (
<TableHeaderColumn
dataField="tableType"
dataFormat={(cell: TableType) => TableTypeLabel[cell]}
Expand Down Expand Up @@ -303,7 +321,7 @@ export function ReplicationTables({
</div>
{isAddTableModalVisible && (
<AddTableModal
isDrInterface={isDrInterface}
isDrInterface={props.isDrInterface}
isVisible={isAddTableModalVisible}
onHide={hideModal}
xClusterConfig={xClusterConfig}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ export const DrConfigDetails = ({ drConfig }: DrConfigDetailsProps) => {
<XClusterMetrics xClusterConfig={xClusterConfig} />
</TabPanel>
<TabPanel value={DrConfigTab.TABLES}>
<ReplicationTables xClusterConfig={xClusterConfig} isDrInterface={true} />
<ReplicationTables
xClusterConfig={xClusterConfig}
isDrInterface={true}
drConfigUuid={drConfig.uuid}
/>
</TabPanel>
</TabContext>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
/* eslint-disable no-console */
import { Typography } from '@material-ui/core';
import { AxiosError } from 'axios';
import { useState } from 'react';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ import {
universeQueryKey,
xClusterQueryKey
} from '../../../../redesign/helpers/api';
import {
fetchTaskUntilItCompletes,
restartXClusterConfig
} from '../../../../actions/xClusterReplication';
import { fetchTaskUntilItCompletes } from '../../../../actions/xClusterReplication';
import { UnavailableUniverseStates } from '../../../../redesign/helpers/constants';
import { getUniverseStatus } from '../../../universes/helpers/universeHelpers';
import { assertUnreachableCase, handleServerError } from '../../../../utils/errorHandlingUtils';
Expand Down Expand Up @@ -204,9 +201,7 @@ export const RepairDrConfigModal = ({ drConfig, modalProps }: RepairDrConfigModa
const xClusterConfig = getXClusterConfig(drConfig);
const restartConfigMutation = useMutation(
(storageConfigUuid: string) => {
return restartXClusterConfig(xClusterConfig.uuid, [], {
backupRequestParams: { storageConfigUUID: storageConfigUuid }
});
return api.restartDrConfig(drConfig.uuid, { dbs: [] });
},
{
onSuccess: (response) => {
Expand Down
2 changes: 1 addition & 1 deletion managed/ui/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@
"confirmationInstructions": "Enter DR replica universe name to confirm.",
"submitButton": "Initiate Switchover",
"note": {
"stopWorkload": "<bold>Stop application workloads</bold> before initiating switchover as all <bold>writes will be rejected</bold> during failover."
"stopWorkload": "<bold>Stop application workloads</bold> before initiating switchover as all <bold>writes will be rejected</bold> during switchover."
},
"error": {
"taskFailure": "Switchover task failed.",
Expand Down

0 comments on commit abcdf7c

Please sign in to comment.