@checkstack/healthcheck-mysql-backend 0.1.13 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/package.json +6 -6
- package/src/query-collector.test.ts +8 -6
- package/src/query-collector.ts +32 -35
- package/src/strategy.test.ts +27 -28
- package/src/strategy.ts +46 -59
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
# @checkstack/healthcheck-mysql-backend
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3dd1914: Migrate health check strategies to VersionedAggregated with \_type discriminator
|
|
8
|
+
|
|
9
|
+
All 13 health check strategies now use `VersionedAggregated` for their `aggregatedResult` property, enabling automatic bucket merging with 100% mathematical fidelity.
|
|
10
|
+
|
|
11
|
+
**Key changes:**
|
|
12
|
+
|
|
13
|
+
- **`_type` discriminator**: All aggregated state objects now include a required `_type` field (`"average"`, `"rate"`, `"counter"`, `"minmax"`) for reliable type detection
|
|
14
|
+
- The `HealthCheckStrategy` interface now requires `aggregatedResult` to be a `VersionedAggregated<AggregatedResultShape>`
|
|
15
|
+
- Strategy/collector `mergeResult` methods return state objects with `_type` (e.g., `{ _type: "average", _sum, _count, avg }`)
|
|
16
|
+
- `mergeAggregatedBucketResults`, `combineBuckets`, and `reaggregateBuckets` now require `registry` and `strategyId` parameters
|
|
17
|
+
- `HealthCheckService` constructor now requires both `registry` and `collectorRegistry` parameters
|
|
18
|
+
- Frontend `extractComputedValue` now uses `_type` discriminator for robust type detection
|
|
19
|
+
|
|
20
|
+
**Breaking Change**: State objects now require `_type`. Merge functions automatically add `_type` to output. The bucket merging functions and `HealthCheckService` now require additional required parameters.
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Updated dependencies [3dd1914]
|
|
25
|
+
- @checkstack/backend-api@0.7.0
|
|
26
|
+
|
|
27
|
+
## 0.1.14
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- 48c2080: Migrate aggregation from batch to incremental (`mergeResult`)
|
|
32
|
+
|
|
33
|
+
### Breaking Changes (Internal)
|
|
34
|
+
|
|
35
|
+
- Replaced `aggregateResult(runs[])` with `mergeResult(existing, run)` interface across all HealthCheckStrategy and CollectorStrategy implementations
|
|
36
|
+
|
|
37
|
+
### New Features
|
|
38
|
+
|
|
39
|
+
- Added incremental aggregation utilities in `@checkstack/backend-api`:
|
|
40
|
+
- `mergeCounter()` - track occurrences
|
|
41
|
+
- `mergeAverage()` - track sum/count, compute avg
|
|
42
|
+
- `mergeRate()` - track success/total, compute %
|
|
43
|
+
- `mergeMinMax()` - track min/max values
|
|
44
|
+
- Exported Zod schemas for internal state: `averageStateSchema`, `rateStateSchema`, `minMaxStateSchema`, `counterStateSchema`
|
|
45
|
+
|
|
46
|
+
### Improvements
|
|
47
|
+
|
|
48
|
+
- Enables O(1) storage overhead by maintaining incremental aggregation state
|
|
49
|
+
- Prepares for real-time hourly aggregation without batch accumulation
|
|
50
|
+
|
|
51
|
+
- Updated dependencies [f676e11]
|
|
52
|
+
- Updated dependencies [48c2080]
|
|
53
|
+
- @checkstack/common@0.6.2
|
|
54
|
+
- @checkstack/backend-api@0.6.0
|
|
55
|
+
- @checkstack/healthcheck-common@0.8.2
|
|
56
|
+
|
|
3
57
|
## 0.1.13
|
|
4
58
|
|
|
5
59
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/healthcheck-mysql-backend",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
"lint:code": "eslint . --max-warnings 0"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@checkstack/backend-api": "0.5.
|
|
13
|
-
"@checkstack/common": "0.6.
|
|
14
|
-
"@checkstack/healthcheck-common": "0.
|
|
12
|
+
"@checkstack/backend-api": "0.5.2",
|
|
13
|
+
"@checkstack/common": "0.6.1",
|
|
14
|
+
"@checkstack/healthcheck-common": "0.8.1",
|
|
15
15
|
"mysql2": "^3.9.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/bun": "^1.0.0",
|
|
19
19
|
"typescript": "^5.0.0",
|
|
20
|
-
"@checkstack/tsconfig": "0.0.
|
|
21
|
-
"@checkstack/scripts": "0.1.
|
|
20
|
+
"@checkstack/tsconfig": "0.0.3",
|
|
21
|
+
"@checkstack/scripts": "0.1.1"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -64,7 +64,7 @@ describe("QueryCollector", () => {
|
|
|
64
64
|
});
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
describe("
|
|
67
|
+
describe("mergeResult", () => {
|
|
68
68
|
it("should calculate average execution time and success rate", () => {
|
|
69
69
|
const collector = new QueryCollector();
|
|
70
70
|
const runs = [
|
|
@@ -86,10 +86,11 @@ describe("QueryCollector", () => {
|
|
|
86
86
|
},
|
|
87
87
|
];
|
|
88
88
|
|
|
89
|
-
|
|
89
|
+
let aggregated = collector.mergeResult(undefined, runs[0]);
|
|
90
|
+
aggregated = collector.mergeResult(aggregated, runs[1]);
|
|
90
91
|
|
|
91
|
-
expect(aggregated.avgExecutionTimeMs).toBe(75);
|
|
92
|
-
expect(aggregated.successRate).toBe(100);
|
|
92
|
+
expect(aggregated.avgExecutionTimeMs.avg).toBe(75);
|
|
93
|
+
expect(aggregated.successRate.rate).toBe(100);
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
it("should calculate success rate correctly", () => {
|
|
@@ -113,9 +114,10 @@ describe("QueryCollector", () => {
|
|
|
113
114
|
},
|
|
114
115
|
];
|
|
115
116
|
|
|
116
|
-
|
|
117
|
+
let aggregated = collector.mergeResult(undefined, runs[0]);
|
|
118
|
+
aggregated = collector.mergeResult(aggregated, runs[1]);
|
|
117
119
|
|
|
118
|
-
expect(aggregated.successRate).toBe(50);
|
|
120
|
+
expect(aggregated.successRate.rate).toBe(50);
|
|
119
121
|
});
|
|
120
122
|
});
|
|
121
123
|
|
package/src/query-collector.ts
CHANGED
|
@@ -4,6 +4,12 @@ import {
|
|
|
4
4
|
type HealthCheckRunForAggregation,
|
|
5
5
|
type CollectorResult,
|
|
6
6
|
type CollectorStrategy,
|
|
7
|
+
mergeAverage,
|
|
8
|
+
mergeRate,
|
|
9
|
+
VersionedAggregated,
|
|
10
|
+
aggregatedAverage,
|
|
11
|
+
aggregatedRate,
|
|
12
|
+
type InferAggregatedResult,
|
|
7
13
|
} from "@checkstack/backend-api";
|
|
8
14
|
import {
|
|
9
15
|
healthResultNumber,
|
|
@@ -45,20 +51,24 @@ const queryResultSchema = healthResultSchema({
|
|
|
45
51
|
|
|
46
52
|
export type QueryResult = z.infer<typeof queryResultSchema>;
|
|
47
53
|
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
// Aggregated result fields definition
|
|
55
|
+
const queryAggregatedFields = {
|
|
56
|
+
avgExecutionTimeMs: aggregatedAverage({
|
|
50
57
|
"x-chart-type": "line",
|
|
51
58
|
"x-chart-label": "Avg Execution Time",
|
|
52
59
|
"x-chart-unit": "ms",
|
|
53
60
|
}),
|
|
54
|
-
successRate:
|
|
61
|
+
successRate: aggregatedRate({
|
|
55
62
|
"x-chart-type": "gauge",
|
|
56
63
|
"x-chart-label": "Success Rate",
|
|
57
64
|
"x-chart-unit": "%",
|
|
58
65
|
}),
|
|
59
|
-
}
|
|
66
|
+
};
|
|
60
67
|
|
|
61
|
-
|
|
68
|
+
// Type inferred from field definitions
|
|
69
|
+
export type QueryAggregatedResult = InferAggregatedResult<
|
|
70
|
+
typeof queryAggregatedFields
|
|
71
|
+
>;
|
|
62
72
|
|
|
63
73
|
// ============================================================================
|
|
64
74
|
// QUERY COLLECTOR
|
|
@@ -68,15 +78,12 @@ export type QueryAggregatedResult = z.infer<typeof queryAggregatedSchema>;
|
|
|
68
78
|
* Built-in MySQL query collector.
|
|
69
79
|
* Executes SQL queries and checks results.
|
|
70
80
|
*/
|
|
71
|
-
export class QueryCollector
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
QueryAggregatedResult
|
|
78
|
-
>
|
|
79
|
-
{
|
|
81
|
+
export class QueryCollector implements CollectorStrategy<
|
|
82
|
+
MysqlTransportClient,
|
|
83
|
+
QueryConfig,
|
|
84
|
+
QueryResult,
|
|
85
|
+
QueryAggregatedResult
|
|
86
|
+
> {
|
|
80
87
|
id = "query";
|
|
81
88
|
displayName = "SQL Query";
|
|
82
89
|
description = "Execute a SQL query and check the result";
|
|
@@ -87,9 +94,9 @@ export class QueryCollector
|
|
|
87
94
|
|
|
88
95
|
config = new Versioned({ version: 1, schema: queryConfigSchema });
|
|
89
96
|
result = new Versioned({ version: 1, schema: queryResultSchema });
|
|
90
|
-
aggregatedResult = new
|
|
97
|
+
aggregatedResult = new VersionedAggregated({
|
|
91
98
|
version: 1,
|
|
92
|
-
|
|
99
|
+
fields: queryAggregatedFields,
|
|
93
100
|
});
|
|
94
101
|
|
|
95
102
|
async execute({
|
|
@@ -115,28 +122,18 @@ export class QueryCollector
|
|
|
115
122
|
};
|
|
116
123
|
}
|
|
117
124
|
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
mergeResult(
|
|
126
|
+
existing: QueryAggregatedResult | undefined,
|
|
127
|
+
run: HealthCheckRunForAggregation<QueryResult>,
|
|
120
128
|
): QueryAggregatedResult {
|
|
121
|
-
const
|
|
122
|
-
.map((r) => r.metadata?.executionTimeMs)
|
|
123
|
-
.filter((v): v is number => typeof v === "number");
|
|
124
|
-
|
|
125
|
-
const successes = runs
|
|
126
|
-
.map((r) => r.metadata?.success)
|
|
127
|
-
.filter((v): v is boolean => typeof v === "boolean");
|
|
128
|
-
|
|
129
|
-
const successCount = successes.filter(Boolean).length;
|
|
129
|
+
const metadata = run.metadata;
|
|
130
130
|
|
|
131
131
|
return {
|
|
132
|
-
avgExecutionTimeMs:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
successRate:
|
|
137
|
-
successes.length > 0
|
|
138
|
-
? Math.round((successCount / successes.length) * 100)
|
|
139
|
-
: 0,
|
|
132
|
+
avgExecutionTimeMs: mergeAverage(
|
|
133
|
+
existing?.avgExecutionTimeMs,
|
|
134
|
+
metadata?.executionTimeMs,
|
|
135
|
+
),
|
|
136
|
+
successRate: mergeRate(existing?.successRate, metadata?.success),
|
|
140
137
|
};
|
|
141
138
|
}
|
|
142
139
|
}
|
package/src/strategy.test.ts
CHANGED
|
@@ -8,7 +8,7 @@ describe("MysqlHealthCheckStrategy", () => {
|
|
|
8
8
|
rowCount?: number;
|
|
9
9
|
queryError?: Error;
|
|
10
10
|
connectError?: Error;
|
|
11
|
-
} = {}
|
|
11
|
+
} = {},
|
|
12
12
|
): DbClient => ({
|
|
13
13
|
connect: mock(() =>
|
|
14
14
|
config.connectError
|
|
@@ -17,10 +17,10 @@ describe("MysqlHealthCheckStrategy", () => {
|
|
|
17
17
|
query: mock(() =>
|
|
18
18
|
config.queryError
|
|
19
19
|
? Promise.reject(config.queryError)
|
|
20
|
-
: Promise.resolve({ rowCount: config.rowCount ?? 1 })
|
|
20
|
+
: Promise.resolve({ rowCount: config.rowCount ?? 1 }),
|
|
21
21
|
),
|
|
22
22
|
end: mock(() => Promise.resolve()),
|
|
23
|
-
})
|
|
23
|
+
}),
|
|
24
24
|
),
|
|
25
25
|
});
|
|
26
26
|
|
|
@@ -46,7 +46,7 @@ describe("MysqlHealthCheckStrategy", () => {
|
|
|
46
46
|
|
|
47
47
|
it("should throw for connection error", async () => {
|
|
48
48
|
const strategy = new MysqlHealthCheckStrategy(
|
|
49
|
-
createMockClient({ connectError: new Error("Connection refused") })
|
|
49
|
+
createMockClient({ connectError: new Error("Connection refused") }),
|
|
50
50
|
);
|
|
51
51
|
|
|
52
52
|
await expect(
|
|
@@ -57,7 +57,7 @@ describe("MysqlHealthCheckStrategy", () => {
|
|
|
57
57
|
user: "root",
|
|
58
58
|
password: "secret",
|
|
59
59
|
timeout: 5000,
|
|
60
|
-
})
|
|
60
|
+
}),
|
|
61
61
|
).rejects.toThrow("Connection refused");
|
|
62
62
|
});
|
|
63
63
|
});
|
|
@@ -85,7 +85,7 @@ describe("MysqlHealthCheckStrategy", () => {
|
|
|
85
85
|
|
|
86
86
|
it("should return error for query error", async () => {
|
|
87
87
|
const strategy = new MysqlHealthCheckStrategy(
|
|
88
|
-
createMockClient({ queryError: new Error("Syntax error") })
|
|
88
|
+
createMockClient({ queryError: new Error("Syntax error") }),
|
|
89
89
|
);
|
|
90
90
|
const connectedClient = await strategy.createClient({
|
|
91
91
|
host: "localhost",
|
|
@@ -107,7 +107,7 @@ describe("MysqlHealthCheckStrategy", () => {
|
|
|
107
107
|
|
|
108
108
|
it("should return custom row count", async () => {
|
|
109
109
|
const strategy = new MysqlHealthCheckStrategy(
|
|
110
|
-
createMockClient({ rowCount: 5 })
|
|
110
|
+
createMockClient({ rowCount: 5 }),
|
|
111
111
|
);
|
|
112
112
|
const connectedClient = await strategy.createClient({
|
|
113
113
|
host: "localhost",
|
|
@@ -128,7 +128,7 @@ describe("MysqlHealthCheckStrategy", () => {
|
|
|
128
128
|
});
|
|
129
129
|
});
|
|
130
130
|
|
|
131
|
-
describe("
|
|
131
|
+
describe("mergeResult", () => {
|
|
132
132
|
it("should calculate averages correctly", () => {
|
|
133
133
|
const strategy = new MysqlHealthCheckStrategy();
|
|
134
134
|
const runs = [
|
|
@@ -158,34 +158,33 @@ describe("MysqlHealthCheckStrategy", () => {
|
|
|
158
158
|
},
|
|
159
159
|
];
|
|
160
160
|
|
|
161
|
-
|
|
161
|
+
let aggregated = strategy.mergeResult(undefined, runs[0]);
|
|
162
|
+
aggregated = strategy.mergeResult(aggregated, runs[1]);
|
|
162
163
|
|
|
163
|
-
expect(aggregated.avgConnectionTime).toBe(75);
|
|
164
|
-
expect(aggregated.successRate).toBe(100);
|
|
165
|
-
expect(aggregated.errorCount).toBe(0);
|
|
164
|
+
expect(aggregated.avgConnectionTime.avg).toBe(75);
|
|
165
|
+
expect(aggregated.successRate.rate).toBe(100);
|
|
166
|
+
expect(aggregated.errorCount.count).toBe(0);
|
|
166
167
|
});
|
|
167
168
|
|
|
168
169
|
it("should count errors", () => {
|
|
169
170
|
const strategy = new MysqlHealthCheckStrategy();
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
error: "Connection refused",
|
|
181
|
-
},
|
|
171
|
+
const run = {
|
|
172
|
+
id: "1",
|
|
173
|
+
status: "unhealthy" as const,
|
|
174
|
+
latencyMs: 100,
|
|
175
|
+
checkId: "c1",
|
|
176
|
+
timestamp: new Date(),
|
|
177
|
+
metadata: {
|
|
178
|
+
connected: false,
|
|
179
|
+
connectionTimeMs: 100,
|
|
180
|
+
error: "Connection refused",
|
|
182
181
|
},
|
|
183
|
-
|
|
182
|
+
};
|
|
184
183
|
|
|
185
|
-
const aggregated = strategy.
|
|
184
|
+
const aggregated = strategy.mergeResult(undefined, run);
|
|
186
185
|
|
|
187
|
-
expect(aggregated.errorCount).toBe(1);
|
|
188
|
-
expect(aggregated.successRate).toBe(0);
|
|
186
|
+
expect(aggregated.errorCount.count).toBe(1);
|
|
187
|
+
expect(aggregated.successRate.rate).toBe(0);
|
|
189
188
|
});
|
|
190
189
|
});
|
|
191
190
|
});
|
package/src/strategy.ts
CHANGED
|
@@ -3,10 +3,20 @@ import {
|
|
|
3
3
|
HealthCheckStrategy,
|
|
4
4
|
HealthCheckRunForAggregation,
|
|
5
5
|
Versioned,
|
|
6
|
+
VersionedAggregated,
|
|
7
|
+
aggregatedAverage,
|
|
8
|
+
aggregatedMinMax,
|
|
9
|
+
aggregatedRate,
|
|
10
|
+
aggregatedCounter,
|
|
11
|
+
mergeAverage,
|
|
12
|
+
mergeRate,
|
|
13
|
+
mergeCounter,
|
|
14
|
+
mergeMinMax,
|
|
6
15
|
z,
|
|
7
16
|
configString,
|
|
8
17
|
configNumber,
|
|
9
18
|
type ConnectedClient,
|
|
19
|
+
type InferAggregatedResult,
|
|
10
20
|
} from "@checkstack/backend-api";
|
|
11
21
|
import {
|
|
12
22
|
healthResultBoolean,
|
|
@@ -68,32 +78,32 @@ const mysqlResultSchema = healthResultSchema({
|
|
|
68
78
|
|
|
69
79
|
type MysqlResult = z.infer<typeof mysqlResultSchema>;
|
|
70
80
|
|
|
71
|
-
/**
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const mysqlAggregatedSchema = healthResultSchema({
|
|
75
|
-
avgConnectionTime: healthResultNumber({
|
|
81
|
+
/** Aggregated field definitions for bucket merging */
|
|
82
|
+
const mysqlAggregatedFields = {
|
|
83
|
+
avgConnectionTime: aggregatedAverage({
|
|
76
84
|
"x-chart-type": "line",
|
|
77
85
|
"x-chart-label": "Avg Connection Time",
|
|
78
86
|
"x-chart-unit": "ms",
|
|
79
87
|
}),
|
|
80
|
-
maxConnectionTime:
|
|
88
|
+
maxConnectionTime: aggregatedMinMax({
|
|
81
89
|
"x-chart-type": "line",
|
|
82
90
|
"x-chart-label": "Max Connection Time",
|
|
83
91
|
"x-chart-unit": "ms",
|
|
84
92
|
}),
|
|
85
|
-
successRate:
|
|
93
|
+
successRate: aggregatedRate({
|
|
86
94
|
"x-chart-type": "gauge",
|
|
87
95
|
"x-chart-label": "Success Rate",
|
|
88
96
|
"x-chart-unit": "%",
|
|
89
97
|
}),
|
|
90
|
-
errorCount:
|
|
98
|
+
errorCount: aggregatedCounter({
|
|
91
99
|
"x-chart-type": "counter",
|
|
92
100
|
"x-chart-label": "Errors",
|
|
93
101
|
}),
|
|
94
|
-
}
|
|
102
|
+
};
|
|
95
103
|
|
|
96
|
-
type MysqlAggregatedResult =
|
|
104
|
+
type MysqlAggregatedResult = InferAggregatedResult<
|
|
105
|
+
typeof mysqlAggregatedFields
|
|
106
|
+
>;
|
|
97
107
|
|
|
98
108
|
// ============================================================================
|
|
99
109
|
// DATABASE CLIENT INTERFACE (for testability)
|
|
@@ -147,15 +157,12 @@ const defaultDbClient: DbClient = {
|
|
|
147
157
|
// STRATEGY
|
|
148
158
|
// ============================================================================
|
|
149
159
|
|
|
150
|
-
export class MysqlHealthCheckStrategy
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
MysqlAggregatedResult
|
|
157
|
-
>
|
|
158
|
-
{
|
|
160
|
+
export class MysqlHealthCheckStrategy implements HealthCheckStrategy<
|
|
161
|
+
MysqlConfig,
|
|
162
|
+
MysqlTransportClient,
|
|
163
|
+
MysqlResult,
|
|
164
|
+
typeof mysqlAggregatedFields
|
|
165
|
+
> {
|
|
159
166
|
id = "mysql";
|
|
160
167
|
displayName = "MySQL Health Check";
|
|
161
168
|
description = "MySQL database connectivity and query health check";
|
|
@@ -192,58 +199,38 @@ export class MysqlHealthCheckStrategy
|
|
|
192
199
|
],
|
|
193
200
|
});
|
|
194
201
|
|
|
195
|
-
aggregatedResult
|
|
202
|
+
aggregatedResult = new VersionedAggregated({
|
|
196
203
|
version: 1,
|
|
197
|
-
|
|
204
|
+
fields: mysqlAggregatedFields,
|
|
198
205
|
});
|
|
199
206
|
|
|
200
|
-
|
|
201
|
-
|
|
207
|
+
mergeResult(
|
|
208
|
+
existing: MysqlAggregatedResult | undefined,
|
|
209
|
+
run: HealthCheckRunForAggregation<MysqlResult>,
|
|
202
210
|
): MysqlAggregatedResult {
|
|
203
|
-
const
|
|
211
|
+
const metadata = run.metadata;
|
|
204
212
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
successRate: 0,
|
|
210
|
-
errorCount: 0,
|
|
211
|
-
};
|
|
212
|
-
}
|
|
213
|
+
const avgConnectionTime = mergeAverage(
|
|
214
|
+
existing?.avgConnectionTime,
|
|
215
|
+
metadata?.connectionTimeMs,
|
|
216
|
+
);
|
|
213
217
|
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
218
|
+
const maxConnectionTime = mergeMinMax(
|
|
219
|
+
existing?.maxConnectionTime,
|
|
220
|
+
metadata?.connectionTimeMs,
|
|
221
|
+
);
|
|
217
222
|
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
? Math.round(
|
|
221
|
-
connectionTimes.reduce((a, b) => a + b, 0) / connectionTimes.length
|
|
222
|
-
)
|
|
223
|
-
: 0;
|
|
223
|
+
const isSuccess = metadata?.connected ?? false;
|
|
224
|
+
const successRate = mergeRate(existing?.successRate, isSuccess);
|
|
224
225
|
|
|
225
|
-
const
|
|
226
|
-
|
|
226
|
+
const hasError = metadata?.error !== undefined;
|
|
227
|
+
const errorCount = mergeCounter(existing?.errorCount, hasError);
|
|
227
228
|
|
|
228
|
-
|
|
229
|
-
(r) => r.metadata?.connected === true
|
|
230
|
-
).length;
|
|
231
|
-
const successRate = Math.round((successCount / validRuns.length) * 100);
|
|
232
|
-
|
|
233
|
-
const errorCount = validRuns.filter(
|
|
234
|
-
(r) => r.metadata?.error !== undefined
|
|
235
|
-
).length;
|
|
236
|
-
|
|
237
|
-
return {
|
|
238
|
-
avgConnectionTime,
|
|
239
|
-
maxConnectionTime,
|
|
240
|
-
successRate,
|
|
241
|
-
errorCount,
|
|
242
|
-
};
|
|
229
|
+
return { avgConnectionTime, maxConnectionTime, successRate, errorCount };
|
|
243
230
|
}
|
|
244
231
|
|
|
245
232
|
async createClient(
|
|
246
|
-
config: MysqlConfigInput
|
|
233
|
+
config: MysqlConfigInput,
|
|
247
234
|
): Promise<ConnectedClient<MysqlTransportClient>> {
|
|
248
235
|
const validatedConfig = this.config.validate(config);
|
|
249
236
|
|