Skip to content

Commit a3cef33

Browse files
authored
test: initial connection strategy integration test (#438)
1 parent 20e0318 commit a3cef33

2 files changed

Lines changed: 211 additions & 0 deletions

File tree

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License").
5+
You may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import { TestEnvironment } from "./utils/test_environment";
18+
import { DriverHelper } from "./utils/driver_helper";
19+
import { AuroraTestUtility } from "./utils/aurora_test_utility";
20+
import { ProxyHelper } from "./utils/proxy_helper";
21+
import { logger } from "../../../../common/logutils";
22+
import { TestEnvironmentFeatures } from "./utils/test_environment_features";
23+
import { features, instanceCount } from "./config";
24+
import { PluginManager } from "../../../../common/lib";
25+
import { RdsHostListProvider } from "../../../../common/lib/host_list_provider/rds_host_list_provider";
26+
import { PluginService } from "../../../../common/lib/plugin_service";
27+
import { AwsWrapperError } from "../../../../common/lib/utils/errors";
28+
29+
const itIf =
30+
!features.includes(TestEnvironmentFeatures.PERFORMANCE) &&
31+
features.includes(TestEnvironmentFeatures.IAM) &&
32+
!features.includes(TestEnvironmentFeatures.RUN_AUTOSCALING_TESTS_ONLY) &&
33+
instanceCount >= 2
34+
? it
35+
: it.skip;
36+
const itIfMinThreeInstance = instanceCount >= 3 ? itIf : it.skip;
37+
38+
let env: TestEnvironment;
39+
let driver;
40+
let initClientFunc: (props: any) => any;
41+
let client: any;
42+
let auroraTestUtility: AuroraTestUtility;
43+
let numReaders: number;
44+
45+
async function initConfig(readerHostSelectorStrategy: string): Promise<any> {
46+
let config: any = {
47+
user: env.databaseInfo.username,
48+
host: env.databaseInfo.clusterReadOnlyEndpoint,
49+
database: env.databaseInfo.defaultDbName,
50+
password: env.databaseInfo.password,
51+
port: env.databaseInfo.clusterEndpointPort,
52+
plugins: "initialConnection",
53+
enableTelemetry: true,
54+
telemetryTracesBackend: "OTLP",
55+
telemetryMetricsBackend: "OTLP",
56+
readerHostSelectorStrategy: readerHostSelectorStrategy
57+
};
58+
59+
config = DriverHelper.addDriverSpecificConfiguration(config, env.engine);
60+
return config;
61+
}
62+
63+
describe("aurora initial connection strategy", () => {
64+
beforeEach(async () => {
65+
logger.info(`Test started: ${expect.getState().currentTestName}`);
66+
env = await TestEnvironment.getCurrent();
67+
auroraTestUtility = new AuroraTestUtility(env.region);
68+
69+
driver = DriverHelper.getDriverForDatabaseEngine(env.engine);
70+
initClientFunc = DriverHelper.getClient(driver);
71+
await ProxyHelper.enableAllConnectivity();
72+
client = null;
73+
await TestEnvironment.verifyClusterStatus();
74+
await TestEnvironment.verifyAllInstancesHasRightState("available");
75+
await TestEnvironment.verifyAllInstancesUp();
76+
77+
RdsHostListProvider.clearAll();
78+
PluginService.clearHostAvailabilityCache();
79+
numReaders = env.databaseInfo.instances.length - 1;
80+
}, 1320000);
81+
82+
afterEach(async () => {
83+
if (client !== null) {
84+
try {
85+
await client.end();
86+
} catch (error) {
87+
// pass
88+
}
89+
}
90+
await PluginManager.releaseResources();
91+
logger.info(`Test finished: ${expect.getState().currentTestName}`);
92+
}, 1320000);
93+
94+
itIf(
95+
"test round robin",
96+
async () => {
97+
const config = await initConfig("roundRobin");
98+
// default weight
99+
config["roundRobinHostWeightPairs"] = null;
100+
const connectedReaderIds: Set<string> = new Set();
101+
const connectionsSet: Set<any> = new Set();
102+
try {
103+
// TODO: fix round robin strategy cached connection issue on first instance
104+
// remove these lines when fixed
105+
const client = initClientFunc(config);
106+
await client.connect();
107+
const readerId = await auroraTestUtility.queryInstanceId(client);
108+
connectionsSet.add(readerId);
109+
110+
for (let i = 0; i < numReaders; i++) {
111+
const client = initClientFunc(config);
112+
await client.connect();
113+
114+
const readerId = await auroraTestUtility.queryInstanceId(client);
115+
expect(connectedReaderIds).not.toContain(readerId);
116+
connectedReaderIds.add(readerId);
117+
connectionsSet.add(client);
118+
}
119+
} finally {
120+
for (const connection of connectionsSet) {
121+
try {
122+
await connection.end();
123+
} catch (error) {
124+
// pass
125+
}
126+
}
127+
}
128+
},
129+
1000000
130+
);
131+
132+
itIfMinThreeInstance(
133+
"test round robin host weight pairs",
134+
async () => {
135+
const connectedReaderIds: Set<string> = new Set();
136+
const connectionsSet: Set<any> = new Set();
137+
const initialReader = env.databaseInfo.readerInstanceId;
138+
const config = await initConfig("roundRobin");
139+
config["roundRobinHostWeightPairs"] = `${initialReader}:${numReaders}`;
140+
141+
// TODO: fix round robin strategy cached connection issue on first instance
142+
// remove these lines when fixed
143+
const client = initClientFunc(config);
144+
await client.connect();
145+
const readerId = await auroraTestUtility.queryInstanceId(client);
146+
connectionsSet.add(readerId);
147+
148+
try {
149+
for (let i = 0; i < numReaders; i++) {
150+
const client = initClientFunc(config);
151+
await client.connect();
152+
153+
const readerId = await auroraTestUtility.queryInstanceId(client);
154+
// All connections should be made to the initial reader with high weight instance.
155+
connectedReaderIds.add(readerId);
156+
connectionsSet.add(client);
157+
expect(connectedReaderIds).toContain(readerId);
158+
expect(connectedReaderIds.size).toBe(1);
159+
}
160+
for (let i = 0; i < numReaders - 1; i++) {
161+
const client = initClientFunc(config);
162+
// All remaining connections should be evenly distributed amongst the other reader instances.
163+
await client.connect();
164+
165+
const readerId = await auroraTestUtility.queryInstanceId(client);
166+
expect(connectedReaderIds).not.toContain(readerId);
167+
connectionsSet.add(client);
168+
}
169+
} finally {
170+
for (const connection of connectionsSet) {
171+
try {
172+
await connection.end();
173+
} catch (error) {
174+
// pass
175+
}
176+
}
177+
}
178+
},
179+
1000000
180+
);
181+
182+
itIf(
183+
"test random initial connection strategy",
184+
async () => {
185+
const config = await initConfig("random");
186+
client = initClientFunc(config);
187+
await client.connect();
188+
await auroraTestUtility.queryInstanceId(client);
189+
},
190+
1000000
191+
);
192+
193+
itIf(
194+
"test invalid initial connection strategy",
195+
async () => {
196+
const config = await initConfig("leastConnections");
197+
// default weight
198+
config["roundRobinHostWeightPairs"] = null;
199+
200+
client = initClientFunc(config);
201+
await expect(async () => {
202+
await client.connect();
203+
}).rejects.toThrow(AwsWrapperError);
204+
},
205+
1000000
206+
);
207+
});

tests/integration/container/tests/utils/test_database_info.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ export class TestDatabaseInfo {
6969
return this._instances[0].instanceId;
7070
}
7171

72+
get readerInstanceId() {
73+
return this._instances[1].instanceId;
74+
}
75+
7276
get clusterEndpoint(): string {
7377
return this._clusterEndpoint;
7478
}

0 commit comments

Comments
 (0)