Skip to content

Commit f253acb

Browse files
committed
feat: gdb failover support
1 parent 00d8176 commit f253acb

111 files changed

Lines changed: 2195 additions & 1561 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/integration_tests.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ on:
55
push:
66
branches:
77
- main
8-
- refactor/monitor-service
98
paths-ignore:
109
- "**/*.md"
1110
- "**/*.jpg"

common/lib/authentication/aws_secrets_manager_plugin.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -129,21 +129,18 @@ export class AwsSecretsManagerPlugin extends AbstractConnectionPlugin implements
129129
this.pluginService.updateConfigWithProperties(props);
130130
return await connectFunc();
131131
} catch (error) {
132-
if (error instanceof Error) {
133-
if ((error.message.includes("password authentication failed") || error.message.includes("Access denied")) && !secretWasFetched) {
134-
// Login unsuccessful with cached credentials
135-
// Try to re-fetch credentials and try again
136-
137-
secretWasFetched = await this.updateSecret(true);
138-
if (secretWasFetched) {
139-
WrapperProperties.USER.set(props, this.secret?.username ?? "");
140-
WrapperProperties.PASSWORD.set(props, this.secret?.password ?? "");
141-
return await connectFunc();
142-
}
132+
if ((error.message.includes("password authentication failed") || error.message.includes("Access denied")) && !secretWasFetched) {
133+
// Login unsuccessful with cached credentials
134+
// Try to re-fetch credentials and try again
135+
136+
secretWasFetched = await this.updateSecret(true);
137+
if (secretWasFetched) {
138+
WrapperProperties.USER.set(props, this.secret?.username ?? "");
139+
WrapperProperties.PASSWORD.set(props, this.secret?.password ?? "");
140+
return await connectFunc();
143141
}
144-
logger.debug(Messages.get("AwsSecretsManagerConnectionPlugin.unhandledError", error.name, error.message));
145142
}
146-
throw error;
143+
logger.debug(Messages.get("AwsSecretsManagerConnectionPlugin.unhandledError", error.name, error.message));
147144
}
148145
}
149146

common/lib/authentication/aws_secrets_manager_plugin_factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class AwsSecretsManagerPluginFactory extends ConnectionPluginFactory {
2828
if (!AwsSecretsManagerPluginFactory.awsSecretsManagerPlugin) {
2929
AwsSecretsManagerPluginFactory.awsSecretsManagerPlugin = await import("./aws_secrets_manager_plugin");
3030
}
31-
return new AwsSecretsManagerPluginFactory.awsSecretsManagerPlugin.AwsSecretsManagerPlugin(servicesContainer.getPluginService(), new Map(properties));
31+
return new AwsSecretsManagerPluginFactory.awsSecretsManagerPlugin.AwsSecretsManagerPlugin(servicesContainer.pluginService, new Map(properties));
3232
} catch (error: any) {
3333
if (error.code === "MODULE_NOT_FOUND") {
3434
throw new AwsWrapperError(Messages.get("ConnectionPluginChainBuilder.errorImportingPlugin", error.message, "AwsSecretsManagerPlugin"));

common/lib/authentication/iam_authentication_plugin_factory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class IamAuthenticationPluginFactory extends ConnectionPluginFactory {
2828
if (!IamAuthenticationPluginFactory.iamAuthenticationPlugin) {
2929
IamAuthenticationPluginFactory.iamAuthenticationPlugin = await import("./iam_authentication_plugin");
3030
}
31-
return new IamAuthenticationPluginFactory.iamAuthenticationPlugin.IamAuthenticationPlugin(servicesContainer.getPluginService());
31+
return new IamAuthenticationPluginFactory.iamAuthenticationPlugin.IamAuthenticationPlugin(servicesContainer.pluginService);
3232
} catch (error: any) {
3333
throw new AwsWrapperError(Messages.get("ConnectionPluginChainBuilder.errorImportingPlugin", error.message, "IamAuthenticationPlugin"));
3434
}

common/lib/aws_client.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export abstract class AwsClient extends EventEmitter implements SessionStateClie
7171

7272
this.properties = new Map<string, any>(Object.entries(config));
7373

74-
this.storageService = CoreServicesContainer.getInstance().getStorageService();
74+
this.storageService = CoreServicesContainer.getInstance().storageService;
7575

7676
const profileName = WrapperProperties.PROFILE_NAME.get(this.properties);
7777
if (profileName && profileName.length > 0) {
@@ -108,9 +108,9 @@ export abstract class AwsClient extends EventEmitter implements SessionStateClie
108108
}
109109

110110
const coreServicesContainer: CoreServicesContainer = CoreServicesContainer.getInstance();
111-
this.storageService = coreServicesContainer.getStorageService();
112-
this.monitorService = coreServicesContainer.getMonitorService();
113-
this.eventPublisher = coreServicesContainer.getEventPublisher();
111+
this.storageService = coreServicesContainer.storageService;
112+
this.monitorService = coreServicesContainer.monitorService;
113+
this.eventPublisher = coreServicesContainer.eventPublisher;
114114
this.telemetryFactory = new DefaultTelemetryFactory(this.properties);
115115

116116
this.fullServiceContainer = ServiceUtils.instance.createStandardServiceContainer(
@@ -126,8 +126,8 @@ export abstract class AwsClient extends EventEmitter implements SessionStateClie
126126
connectionProvider
127127
);
128128

129-
this.pluginService = this.fullServiceContainer.getPluginService();
130-
this.pluginManager = this.fullServiceContainer.getPluginManager();
129+
this.pluginService = this.fullServiceContainer.pluginService;
130+
this.pluginManager = this.fullServiceContainer.pluginManager;
131131
}
132132

133133
private async setup() {
@@ -144,7 +144,7 @@ export abstract class AwsClient extends EventEmitter implements SessionStateClie
144144
await this.pluginService.refreshHostList();
145145
const initialHostInfo = this.pluginService.getInitialConnectionHostInfo();
146146
if (initialHostInfo != null) {
147-
await this.pluginManager.initHostProvider(initialHostInfo, this.properties, this.fullServiceContainer.getHostListProviderService());
147+
await this.pluginManager.initHostProvider(initialHostInfo, this.properties, this.fullServiceContainer.hostListProviderService);
148148
await this.pluginService.refreshHostList();
149149
}
150150
}

common/lib/connection_plugin_chain_builder.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { CustomEndpointPluginFactory } from "./plugins/custom_endpoint/custom_en
4343
import { ConfigurationProfile } from "./profile/configuration_profile";
4444
import { HostMonitoring2PluginFactory } from "./plugins/efm2/host_monitoring2_plugin_factory";
4545
import { BlueGreenPluginFactory } from "./plugins/bluegreen/blue_green_plugin_factory";
46+
import { GlobalDbFailoverPluginFactory } from "./plugins/gdb_failover/global_db_failover_plugin_factory";
4647
import { FullServicesContainer } from "./utils/full_services_container";
4748

4849
/*
@@ -66,6 +67,7 @@ export class ConnectionPluginChainBuilder {
6667
["readWriteSplitting", { factory: ReadWriteSplittingPluginFactory, weight: 600 }],
6768
["failover", { factory: FailoverPluginFactory, weight: 700 }],
6869
["failover2", { factory: Failover2PluginFactory, weight: 710 }],
70+
["gdbFailover", { factory: GlobalDbFailoverPluginFactory, weight: 720 }],
6971
["efm", { factory: HostMonitoringPluginFactory, weight: 800 }],
7072
["efm2", { factory: HostMonitoring2PluginFactory, weight: 810 }],
7173
["fastestResponseStrategy", { factory: FastestResponseStrategyPluginFactory, weight: 900 }],
@@ -87,6 +89,7 @@ export class ConnectionPluginChainBuilder {
8789
[ReadWriteSplittingPluginFactory, 600],
8890
[FailoverPluginFactory, 700],
8991
[Failover2PluginFactory, 710],
92+
[GlobalDbFailoverPluginFactory, 720],
9093
[HostMonitoringPluginFactory, 800],
9194
[HostMonitoring2PluginFactory, 810],
9295
[LimitlessConnectionPluginFactory, 950],

common/lib/database_dialect/database_dialect_codes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
*/
1616

1717
export class DatabaseDialectCodes {
18+
static readonly GLOBAL_AURORA_MYSQL: string = "global-aurora-mysql";
1819
static readonly AURORA_MYSQL: string = "aurora-mysql";
1920
static readonly RDS_MYSQL: string = "rds-mysql";
2021
static readonly MYSQL: string = "mysql";
2122
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html
2223
static readonly RDS_MULTI_AZ_MYSQL: string = "rds-multi-az-mysql";
24+
static readonly GLOBAL_AURORA_PG: string = "global-aurora-pg";
2325
static readonly AURORA_PG: string = "aurora-pg";
2426
static readonly RDS_PG: string = "rds-pg";
2527
// https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/multi-az-db-clusters-concepts.html

common/lib/database_dialect/database_dialect_manager.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,14 @@ export class DatabaseDialectManager implements DatabaseDialectProvider {
9595

9696
if (this.dbType === DatabaseType.MYSQL) {
9797
const type = this.rdsHelper.identifyRdsType(host);
98+
if (type == RdsUrlType.RDS_GLOBAL_WRITER_CLUSTER) {
99+
this.canUpdate = false;
100+
this.dialectCode = DatabaseDialectCodes.GLOBAL_AURORA_MYSQL;
101+
this.dialect = <DatabaseDialect>this.knownDialectsByCode.get(DatabaseDialectCodes.GLOBAL_AURORA_MYSQL);
102+
this.logCurrentDialect();
103+
return this.dialect;
104+
}
105+
98106
if (type.isRdsCluster) {
99107
this.canUpdate = true;
100108
this.dialectCode = DatabaseDialectCodes.AURORA_MYSQL;
@@ -128,6 +136,14 @@ export class DatabaseDialectManager implements DatabaseDialectProvider {
128136
return this.dialect;
129137
}
130138

139+
if (type == RdsUrlType.RDS_GLOBAL_WRITER_CLUSTER) {
140+
this.canUpdate = false;
141+
this.dialectCode = DatabaseDialectCodes.GLOBAL_AURORA_PG;
142+
this.dialect = <DatabaseDialect>this.knownDialectsByCode.get(DatabaseDialectCodes.GLOBAL_AURORA_PG);
143+
this.logCurrentDialect();
144+
return this.dialect;
145+
}
146+
131147
if (type.isRdsCluster) {
132148
this.canUpdate = true;
133149
this.dialectCode = DatabaseDialectCodes.AURORA_PG;

common/lib/driver_dialect/driver_dialect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export interface DriverDialect {
3030

3131
setConnectTimeout(props: Map<string, any>, wrapperConnectTimeout?: any): void;
3232

33-
setQueryTimeout(props: Map<string, any>, sql?: any, wrapperConnectTimeout?: any): void;
33+
setQueryTimeout(props: Map<string, any>, sql?: any, wrapperQueryTimeout?: any): void;
3434

3535
setKeepAliveProperties(props: Map<string, any>, keepAliveProps: any): void;
3636

common/lib/highest_weight_host_selector.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export class HighestWeightHostSelector implements HostSelector {
2626

2727
getHost(hosts: HostInfo[], role: HostRole, props?: Map<string, any>): HostInfo {
2828
const eligibleHosts: HostInfo[] = hosts
29-
.filter((host: HostInfo) => host.role === role && host.availability === HostAvailability.AVAILABLE)
29+
.filter((host: HostInfo) => (role === null || host.role === role) && host.availability === HostAvailability.AVAILABLE)
3030
.sort((hostA: HostInfo, hostB: HostInfo) => (hostA.weight > hostB.weight ? -1 : hostA.weight < hostB.weight ? 1 : 0));
3131

3232
if (eligibleHosts.length === 0) {

0 commit comments

Comments
 (0)