Skip to content

Commit 502eb06

Browse files
fix(datasource): datasource sync failed (#3829)
* fix sync ds * code format
1 parent beee9c9 commit 502eb06

File tree

4 files changed

+63
-53
lines changed

4 files changed

+63
-53
lines changed

server/odc-service/src/main/java/com/oceanbase/odc/config/ScheduleConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ public ThreadPoolTaskExecutor syncDatabaseTaskExecutor() {
195195
executor.setWaitForTasksToCompleteOnShutdown(true);
196196
executor.setAwaitTerminationSeconds(5);
197197
executor.setTaskDecorator(new TraceDecorator<>());
198-
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
198+
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
199199
executor.initialize();
200200
log.info("syncDatabaseTaskExecutor initialized");
201201
return executor;

server/odc-service/src/main/java/com/oceanbase/odc/service/connection/DatabaseSyncSchedules.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.oceanbase.odc.service.connection;
1717

18+
import java.util.Collections;
1819
import java.util.List;
1920

2021
import org.springframework.beans.factory.annotation.Autowired;
@@ -49,6 +50,8 @@ public void syncDatabases() {
4950
if (CollectionUtils.isEmpty(orgDataSources)) {
5051
return;
5152
}
53+
Collections.shuffle(orgDataSources);
54+
log.info("Start to sync datasources, size={}", orgDataSources.size());
5255
for (ConnectionConfig dataSource : orgDataSources) {
5356
try {
5457
databaseSyncManager.submitSyncDataSourceTask(dataSource);

server/odc-service/src/main/java/com/oceanbase/odc/service/connection/database/DatabaseService.java

Lines changed: 58 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package com.oceanbase.odc.service.connection.database;
1717

1818
import java.sql.Connection;
19-
import java.sql.SQLException;
2019
import java.util.ArrayList;
2120
import java.util.Arrays;
2221
import java.util.Collection;
@@ -27,6 +26,7 @@
2726
import java.util.List;
2827
import java.util.Map;
2928
import java.util.Objects;
29+
import java.util.Optional;
3030
import java.util.Set;
3131
import java.util.TreeSet;
3232
import java.util.concurrent.ExecutionException;
@@ -72,6 +72,7 @@
7272
import com.oceanbase.odc.core.shared.exception.BadRequestException;
7373
import com.oceanbase.odc.core.shared.exception.ConflictException;
7474
import com.oceanbase.odc.core.shared.exception.NotFoundException;
75+
import com.oceanbase.odc.core.shared.exception.UnexpectedException;
7576
import com.oceanbase.odc.metadb.connection.DatabaseEntity;
7677
import com.oceanbase.odc.metadb.connection.DatabaseRepository;
7778
import com.oceanbase.odc.metadb.connection.DatabaseSpecs;
@@ -115,6 +116,7 @@
115116
import com.oceanbase.odc.service.iam.ResourceRoleService;
116117
import com.oceanbase.odc.service.iam.UserService;
117118
import com.oceanbase.odc.service.iam.auth.AuthenticationFacade;
119+
import com.oceanbase.odc.service.iam.model.Organization;
118120
import com.oceanbase.odc.service.iam.model.User;
119121
import com.oceanbase.odc.service.iam.model.UserResourceRole;
120122
import com.oceanbase.odc.service.monitor.datasource.GetConnectionFailedEventListener;
@@ -512,19 +514,24 @@ public Boolean internalSyncDataSourceSchemas(@NonNull Long dataSourceId) throws
512514
throw new ConflictException(ErrorCodes.ResourceSynchronizing,
513515
new Object[] {ResourceType.ODC_DATABASE.getLocalizedMessage()}, "Can not acquire jdbc lock");
514516
}
517+
ConnectionConfig connection;
518+
Optional<Organization> organizationOpt = Optional.empty();
515519
try {
516-
ConnectionConfig connection = connectionService.getForConnectionSkipPermissionCheck(dataSourceId);
520+
connection = connectionService.getForConnectionSkipPermissionCheck(dataSourceId);
517521
horizontalDataPermissionValidator.checkCurrentOrganization(connection);
518-
organizationService.get(connection.getOrganizationId()).ifPresent(organization -> {
519-
if (organization.getType() == OrganizationType.INDIVIDUAL) {
520-
syncIndividualDataSources(connection);
521-
} else {
522-
syncTeamDataSources(connection);
523-
}
524-
});
522+
organizationOpt = organizationService.get(connection.getOrganizationId());
523+
Organization organization =
524+
organizationOpt.orElseThrow(() -> new UnexpectedException("Organization not found"));
525+
if (organization.getType() == OrganizationType.INDIVIDUAL) {
526+
syncIndividualDataSources(connection);
527+
} else {
528+
syncTeamDataSources(connection);
529+
}
530+
connectionSyncHistoryService.upsert(connection.getId(), ConnectionSyncResult.SUCCESS,
531+
connection.getOrganizationId(), null, null);
525532
return true;
526533
} catch (Exception ex) {
527-
log.warn("Sync database failed, dataSourceId={}, errorMessage={}", dataSourceId, ex.getLocalizedMessage());
534+
handleSyncException(ex, dataSourceId, organizationOpt);
528535
return false;
529536
} finally {
530537
lock.unlock();
@@ -535,7 +542,8 @@ public int updateEnvironmentIdByConnectionId(@NotNull Long environmentId, @NotNu
535542
return databaseRepository.setEnvironmentIdByConnectionId(environmentId, connectionId);
536543
}
537544

538-
private void syncTeamDataSources(ConnectionConfig connection) {
545+
private void syncTeamDataSources(ConnectionConfig connection)
546+
throws ExecutionException, InterruptedException, TimeoutException {
539547
Long currentProjectId = connection.getProjectId();
540548
boolean blockExcludeSchemas = dbSchemaSyncProperties.isBlockExclusionsWhenSyncDbToProject();
541549
List<String> excludeSchemas = dbSchemaSyncProperties.getExcludeSchemas(connection.getDialectType());
@@ -633,20 +641,6 @@ private void syncTeamDataSources(ConnectionConfig connection) {
633641
}
634642
connectionSyncHistoryService.upsert(connection.getId(), ConnectionSyncResult.SUCCESS,
635643
connection.getOrganizationId(), null, null);
636-
} catch (ExecutionException | InterruptedException | TimeoutException e) {
637-
String errorMessage = e.getMessage();
638-
Throwable rootCause = e.getCause();
639-
ConnectionSyncErrorReason failedReason = ConnectionSyncErrorReason.UNKNOWN;
640-
log.warn("Failed to obtain the connection, errorMessage={}", errorMessage);
641-
if (rootCause instanceof SQLException
642-
&& StringUtils.containsIgnoreCase(errorMessage, "cluster not exist")) {
643-
failedReason = ConnectionSyncErrorReason.CLUSTER_NOT_EXISTS;
644-
deleteDatabaseIfClusterNotExists((SQLException) rootCause,
645-
connection.getId(), "update connect_database set is_existed = 0 where connection_id=?");
646-
}
647-
connectionSyncHistoryService.upsert(connection.getId(), ConnectionSyncResult.FAILURE,
648-
connection.getOrganizationId(), failedReason,
649-
rootCause.getMessage());
650644
} finally {
651645
try {
652646
executorService.shutdownNow();
@@ -685,7 +679,8 @@ private Long getProjectId(DatabaseEntity database, Long currentProjectId, List<S
685679
return projectId;
686680
}
687681

688-
private void syncIndividualDataSources(ConnectionConfig connection) {
682+
private void syncIndividualDataSources(ConnectionConfig connection)
683+
throws ExecutionException, InterruptedException, TimeoutException {
689684
DataSource individualDataSource = getDataSourceFactory(connection).getDataSource();
690685
ExecutorService executorService = Executors.newFixedThreadPool(1);
691686
Future<Set<String>> future = executorService.submit(() -> {
@@ -733,20 +728,6 @@ private void syncIndividualDataSources(ConnectionConfig connection) {
733728
}
734729
connectionSyncHistoryService.upsert(connection.getId(), ConnectionSyncResult.SUCCESS,
735730
connection.getOrganizationId(), null, null);
736-
} catch (ExecutionException | InterruptedException | TimeoutException e) {
737-
String errorMessage = e.getMessage();
738-
Throwable rootCause = e.getCause();
739-
ConnectionSyncErrorReason failedReason = ConnectionSyncErrorReason.UNKNOWN;
740-
log.warn("Failed to obtain the connection, errorMessage={}", errorMessage);
741-
if (rootCause instanceof SQLException
742-
&& StringUtils.containsIgnoreCase(errorMessage, "cluster not exist")) {
743-
failedReason = ConnectionSyncErrorReason.CLUSTER_NOT_EXISTS;
744-
deleteDatabaseIfClusterNotExists((SQLException) rootCause,
745-
connection.getId(), "delete from connect_database where connection_id=?");
746-
}
747-
connectionSyncHistoryService.upsert(connection.getId(), ConnectionSyncResult.FAILURE,
748-
connection.getOrganizationId(), failedReason,
749-
rootCause.getMessage());
750731
} finally {
751732
try {
752733
executorService.shutdownNow();
@@ -1056,19 +1037,44 @@ private List<UserResourceRole> buildUserResourceRoles(Collection<Long> databaseI
10561037
return userResourceRoles;
10571038
}
10581039

1040+
private void handleSyncException(@NonNull Exception ex, @NonNull Long dataSourceId,
1041+
@NonNull Optional<Organization> organizationOpt) {
1042+
String errorMessage = ex.getMessage();
1043+
log.warn("Sync database failed, dataSourceId={}, errorMessage={}", dataSourceId, errorMessage);
1044+
if (!organizationOpt.isPresent()) {
1045+
return;
1046+
}
1047+
Organization organization = organizationOpt.get();
1048+
ConnectionSyncErrorReason failedReason = ConnectionSyncErrorReason.UNKNOWN;
1049+
if (StringUtils.containsIgnoreCase(errorMessage, "cluster not exist")) {
1050+
failedReason = ConnectionSyncErrorReason.CLUSTER_NOT_EXISTS;
1051+
deleteDatabaseIfInstanceNotExists(dataSourceId, organization.getType());
1052+
} else if (StringUtils.containsIgnoreCase(errorMessage, "No tenants found") || StringUtils
1053+
.containsIgnoreCase(errorMessage, "tenant expected 1 but was")) {
1054+
failedReason = ConnectionSyncErrorReason.TENANT_NOT_EXISTS;
1055+
deleteDatabaseIfInstanceNotExists(dataSourceId, organization.getType());
1056+
}
1057+
connectionSyncHistoryService.upsert(dataSourceId, ConnectionSyncResult.FAILURE, organization.getId(),
1058+
failedReason, errorMessage);
1059+
}
10591060

1060-
private void deleteDatabaseIfClusterNotExists(SQLException e, Long connectionId, String deleteSql) {
1061-
if (StringUtils.containsIgnoreCase(e.getMessage(), "cluster not exist")) {
1062-
log.info(
1063-
"Cluster not exist, set existed to false for all databases in this data source, data source id = {}",
1064-
connectionId);
1065-
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
1066-
try {
1067-
jdbcTemplate.update(deleteSql, new Object[] {connectionId});
1068-
} catch (Exception ex) {
1069-
log.warn("Failed to delete databases when cluster not exist, errorMessage={}",
1070-
ex.getLocalizedMessage());
1071-
}
1061+
private void deleteDatabaseIfInstanceNotExists(Long connectionId, OrganizationType organizationType) {
1062+
log.info(
1063+
"Cluster or tenant not exist, set existed to false for all databases in this data source, data source id = {}",
1064+
connectionId);
1065+
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
1066+
String deleteSql;
1067+
if (organizationType == OrganizationType.INDIVIDUAL) {
1068+
deleteSql = "delete from connect_database where connection_id=?";
1069+
} else {
1070+
deleteSql = "update connect_database set is_existed = 0 where connection_id=?";
10721071
}
1072+
try {
1073+
jdbcTemplate.update(deleteSql, connectionId);
1074+
} catch (Exception ex) {
1075+
log.warn("Failed to delete databases when cluster not exist, errorMessage={}",
1076+
ex.getLocalizedMessage());
1077+
}
1078+
10731079
}
10741080
}

server/odc-service/src/main/java/com/oceanbase/odc/service/connection/model/ConnectionSyncErrorReason.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717

1818
public enum ConnectionSyncErrorReason {
1919
CLUSTER_NOT_EXISTS,
20+
TENANT_NOT_EXISTS,
2021
UNKNOWN,
2122
}

0 commit comments

Comments
 (0)