Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: custom endpoint plugin #369

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

crystall-bitquill
Copy link
Contributor

@crystall-bitquill crystall-bitquill commented Jan 14, 2025

Summary

Custom Endpoint Plugin

Description

  • Adds the custom endpoint plugin
  • Implements setAvailability in PluginService
  • Moves getRegion in the IamAuthUtils to RegionUtils
  • Fixes the MySQL database dialect getHostRole method - previously the query result was not being parsed correctly

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@crystall-bitquill crystall-bitquill added the ready for review Pull requests that are ready to be reviewed label Jan 14, 2025
afterEach(async () => {
if (client !== null) {
try {
await client.end();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to clear the cache each test run via PluginManager.releaseResources()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, releaseResources is called below this line

@crystall-bitquill crystall-bitquill force-pushed the feat/custom-endpoints branch 6 times, most recently from cc6f3be to 33a53d9 Compare January 24, 2025 00:43
@@ -104,6 +104,7 @@ describe("aurora read write splitting", () => {
await TestEnvironment.verifyClusterStatus();
await TestEnvironment.verifyAllInstancesHasRightState("available");
await TestEnvironment.verifyAllInstancesUp();
await PluginManager.releaseResources();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resources are already being released in afterEach - what is needing to be cleaned up here?

@@ -135,7 +134,11 @@ export class AuroraTestUtility {
return clusters[0];
}

async failoverClusterAndWaitUntilWriterChanged(initialWriter?: string, clusterId?: string) {
async failoverClusterToATargetAndWaitUntilWriterChanged(clusterId: string, initialWriterId: string, targetWriterId: string): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can just directly call this.failoverClusterAndWaitUntilWriterChanged instead of using this method.

@@ -148,7 +151,11 @@ export class AuroraTestUtility {
const clusterEndpoint = databaseInfo.clusterEndpoint;
const initialClusterAddress = await dns.promises.lookup(clusterEndpoint);

await this.failoverCluster(clusterId);
if (targetWriterId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can pass targetWriterId directly to failoverClusterToTarget as it checks for it there

@@ -157,7 +164,11 @@ export class AuroraTestUtility {
throw new Error("failover request unsuccessful");
}

await this.failoverCluster(clusterId);
if (targetWriterId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above

@@ -56,6 +56,7 @@ describe("reader failover handler", () => {
const currentHostIndex = 2;
const successHostIndex = 3;

when(mockPluginService.getAllHosts()).thenReturn(hosts);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can remove the line for getHosts from this file too

@@ -0,0 +1,28 @@
# Custom Endpoint Plugin

The Custom Endpoint Plugin adds support for RDS custom endpoints. When the Custom Endpoint Plugin is in use, the driver will analyse custom endpoint information to ensure instances used in connections are part of the custom endpoint being used. This includes connections used in failover and read-write splitting.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The Custom Endpoint Plugin adds support for RDS custom endpoints. When the Custom Endpoint Plugin is in use, the driver will analyse custom endpoint information to ensure instances used in connections are part of the custom endpoint being used. This includes connections used in failover and read-write splitting.
The Custom Endpoint Plugin adds support for [RDS custom endpoints](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Endpoints.Custom.html). When the Custom Endpoint Plugin is in use, the driver will analyse custom endpoint information to ensure instances used in connections are part of the custom endpoint being used. This includes connections used in failover and read-write splitting.
Suggested change
The Custom Endpoint Plugin adds support for RDS custom endpoints. When the Custom Endpoint Plugin is in use, the driver will analyse custom endpoint information to ensure instances used in connections are part of the custom endpoint being used. This includes connections used in failover and read-write splitting.
The Custom Endpoint Plugin adds support for RDS custom endpoints. When the Custom Endpoint Plugin is in use, the driver will analyse custom endpoint information to ensure instances used in connections are part of the custom endpoint being used. This includes connections used in failover and read-write splitting.


export class CustomEndpointPlugin extends AbstractConnectionPlugin implements CanReleaseResources {
private static readonly TELEMETRY_WAIT_FOR_INFO_COUNTER = "customEndpoint.waitForInfo.counter";
private static SUBSCRIBED_METHODS: Set<string> = new Set<string>(["connect", "forceConnect"].concat(SubscribedMethodHelper.NETWORK_BOUND_METHODS));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
private static SUBSCRIBED_METHODS: Set<string> = new Set<string>(["connect", "forceConnect"].concat(SubscribedMethodHelper.NETWORK_BOUND_METHODS));
private static SUBSCRIBED_METHODS: Set<string> = new Set<string>(SubscribedMethodHelper.NETWORK_BOUND_METHODS);

static closeMonitors() {
logger.info(Messages.get("CustomEndpointPlugin.closeMonitors"));
// The clear call automatically calls close() on all monitors.
CustomEndpointPlugin.monitors.clear();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does monitors need similar handling such as a for loop through each monitor as releaseResources in MonitorService?

}

createMonitorIfAbsent(props: Map<string, any>): CustomEndpointMonitor {
return CustomEndpointPlugin.monitors.computeIfAbsent(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should check if there is already a monitor for this host before calling new CustomEndpointMonitorImpl - in the constructor it has a call to run and this might leave some hanging resources if a monitor already exists

return CustomEndpointMonitorImpl.customEndpointInfoCache.get(this.customEndpointHostInfo.host) != null;
}

shouldDispose(): boolean {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could instead just return true in the initialization of the monitors in custom_endpoint_plugin

);

itIf(
"test custom endpoint read write splitting with custom endpoint changes",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if this should be separated into two tests, one with a single host and one with multiple?

port: port,
plugins: "customEndpoint,readWriteSplitting,failover",
failoverTimeoutMs: 250000,
failoverMode: "reader-or-writer",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to also test another failoverMode?

it("test get hosts - allowed hosts empty", async () => {
pluginService.setHosts(allHosts);
const allowedHosts = new Set<string>();
const blockedHosts = new Set<string>(["host-3", "host-4"]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: change blockedHosts here to at least have one different outcome in your tests.

Suggested change
const blockedHosts = new Set<string>(["host-3", "host-4"]);
const blockedHosts = new Set<string>(["host-1", "host-2"]);

expect(captureResult[0].getBlockedHostIds()).toBeNull();

// Wait for monitor to close
await sleep(100);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to incorporate this necessary waiting into monitor.close()I think we already have some time waiting set there?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready for review Pull requests that are ready to be reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants