Skip to content

Commit

Permalink
[PLAT-16152] Correctly delete PITR configs on A -> B and A -> C xclus…
Browse files Browse the repository at this point in the history
…ter config setups with same db

Summary:
Allows PITR config to be correctly deleted for DR/xcluster configurations with A -> B and A -> C setups using the same databases. The databases on A will use the same PITR configs for both replications. Hence, make sure that if A -> B or A -> C is deleted, the pitr configs on A are retained and not deleted.

Note that there are still issues with A -> B and A -> C if the pitr params are different which cannot be solved with the current implementation.

Test Plan:
UTs

Manually tested following flow:
Create A -> B and A -> C with the same database and pitr params. Check that there is one pitr config for the database on A. Delete A -> C replication. Validate that the pitr conifg

Reviewers: hzare, jmak

Reviewed By: hzare

Subscribers: yugaware

Differential Revision: https://phorge.dev.yugabyte.com/D41172
  • Loading branch information
charleswang234 committed Jan 24, 2025
1 parent 8eb2b28 commit 0f80d46
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -5951,7 +5951,8 @@ protected void createDeleteXClusterConfigSubtasks(
&& pitrConfig
.getUniverse()
.getUniverseUUID()
.equals(xClusterConfig.getSourceUniverseUUID()))
.equals(xClusterConfig.getSourceUniverseUUID())
&& pitrConfig.getXClusterConfigs().size() <= 1)
|| (deleteTargetPitrConfigs
&& pitrConfig
.getUniverse()
Expand Down
11 changes: 11 additions & 0 deletions managed/src/main/java/com/yugabyte/yw/models/PitrConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.yugabyte.yw.common.PlatformServiceException;
import com.yugabyte.yw.forms.CreatePitrConfigParams;
Expand All @@ -27,6 +28,7 @@
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -161,4 +163,13 @@ public boolean isUsedForXCluster() {
List<SqlRow> sqlRow = DB.sqlQuery(sqlStatement).setParameter("pitrUuid", this.uuid).findList();
return !sqlRow.isEmpty();
}

@JsonIgnore
public List<XClusterConfig> getXClusterConfigs() {
String sqlStatement = "SELECT xcluster_uuid FROM xcluster_pitr WHERE pitr_uuid = :pitrUuid";
List<SqlRow> sqlRow = DB.sqlQuery(sqlStatement).setParameter("pitrUuid", this.uuid).findList();
return sqlRow.stream()
.map(row -> XClusterConfig.getOrBadRequest(UUID.fromString(row.getString("xcluster_uuid"))))
.collect(Collectors.toList());
}
}
103 changes: 103 additions & 0 deletions managed/src/test/java/com/yugabyte/yw/models/PitrConfigTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) YugaByte, Inc.
package com.yugabyte.yw.models;

import static com.yugabyte.yw.common.ModelFactory.createUniverse;
import static org.junit.Assert.assertEquals;

import com.fasterxml.jackson.databind.JsonNode;
import com.yugabyte.yw.common.FakeDBApplication;
import com.yugabyte.yw.common.ModelFactory;
import com.yugabyte.yw.forms.CreatePitrConfigParams;
import com.yugabyte.yw.forms.DrConfigCreateForm.PitrParams;
import com.yugabyte.yw.forms.XClusterConfigCreateFormData.BootstrapParams.BootstrapBackupParams;
import com.yugabyte.yw.models.configs.CustomerConfig;
import java.util.Set;
import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import org.yb.CommonTypes.TableType;
import play.libs.Json;

public class PitrConfigTest extends FakeDBApplication {

private CustomerConfig config;

@Before
public void setUp() {
Customer defaultCustomer = ModelFactory.testCustomer();
config = createData(defaultCustomer);
}

private CustomerConfig createData(Customer customer) {
JsonNode formData =
Json.parse(
"{\"name\": \"Test\", \"configName\": \"Test\", \"type\": "
+ "\"STORAGE\", \"data\": {\"foo\": \"bar\"},"
+ "\"configUUID\": \"5e8e4887-343b-47dd-a126-71c822904c06\"}");
return CustomerConfig.createWithFormData(customer.getUuid(), formData);
}

@Test
public void testPitrConfigXClusterCount() {

Universe sourceUniverse = createUniverse("source Universe");
Universe targetUniverse = createUniverse("target Universe");

BootstrapBackupParams backupRequestParams;
backupRequestParams = new BootstrapBackupParams();
backupRequestParams.storageConfigUUID = config.getConfigUUID();

Set<String> sourceDbIds = Set.of("db1", "db2");
DrConfig drConfig1 =
DrConfig.create(
"replication1",
sourceUniverse.getUniverseUUID(),
targetUniverse.getUniverseUUID(),
backupRequestParams,
new PitrParams(),
sourceDbIds);
XClusterConfig xClusterConfig1 = drConfig1.getActiveXClusterConfig();

CreatePitrConfigParams createPitrConfigParams = new CreatePitrConfigParams();
createPitrConfigParams.setUniverseUUID(sourceUniverse.getUniverseUUID());
createPitrConfigParams.customerUUID = Customer.get(sourceUniverse.getCustomerId()).getUuid();
createPitrConfigParams.name = null;
createPitrConfigParams.keyspaceName = "mockNamespace";
createPitrConfigParams.tableType = TableType.PGSQL_TABLE_TYPE;
createPitrConfigParams.retentionPeriodInSeconds = 1;
createPitrConfigParams.xClusterConfig = xClusterConfig1;
createPitrConfigParams.intervalInSeconds = 1;
createPitrConfigParams.createdForDr = true;

PitrConfig pitrConfig = PitrConfig.create(UUID.randomUUID(), createPitrConfigParams);
xClusterConfig1.addPitrConfig(pitrConfig);
pitrConfig.refresh();

assertEquals(1, pitrConfig.getXClusterConfigs().size());
assertEquals(xClusterConfig1.getUuid(), pitrConfig.getXClusterConfigs().get(0).getUuid());

Universe secondTargetUniverse = createUniverse("second target Universe");
// A -> B and A -> C.
DrConfig drConfig2 =
DrConfig.create(
"replication2",
sourceUniverse.getUniverseUUID(),
secondTargetUniverse.getUniverseUUID(),
backupRequestParams,
new PitrParams(),
sourceDbIds);
XClusterConfig xClusterConfig2 = drConfig2.getActiveXClusterConfig();
xClusterConfig2.addPitrConfig(pitrConfig);

// Pitr Config is associated to 2 xcluster configs.
pitrConfig.refresh();
assertEquals(2, pitrConfig.getXClusterConfigs().size());
assertEquals(xClusterConfig2.getUuid(), pitrConfig.getXClusterConfigs().get(1).getUuid());

// xcluster_pitr should be cascade deleted when xcluster config is deleted.
xClusterConfig2.delete();
pitrConfig.refresh();
assertEquals(1, pitrConfig.getXClusterConfigs().size());
assertEquals(xClusterConfig1.getUuid(), pitrConfig.getXClusterConfigs().get(0).getUuid());
}
}

0 comments on commit 0f80d46

Please sign in to comment.