@checkstack/healthcheck-dns-backend 0.1.13 → 0.1.14
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 +30 -0
- package/package.json +6 -6
- package/src/lookup-collector.test.ts +10 -4
- package/src/lookup-collector.ts +44 -27
- package/src/strategy.test.ts +18 -14
- package/src/strategy.ts +66 -42
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @checkstack/healthcheck-dns-backend
|
|
2
2
|
|
|
3
|
+
## 0.1.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 48c2080: Migrate aggregation from batch to incremental (`mergeResult`)
|
|
8
|
+
|
|
9
|
+
### Breaking Changes (Internal)
|
|
10
|
+
|
|
11
|
+
- Replaced `aggregateResult(runs[])` with `mergeResult(existing, run)` interface across all HealthCheckStrategy and CollectorStrategy implementations
|
|
12
|
+
|
|
13
|
+
### New Features
|
|
14
|
+
|
|
15
|
+
- Added incremental aggregation utilities in `@checkstack/backend-api`:
|
|
16
|
+
- `mergeCounter()` - track occurrences
|
|
17
|
+
- `mergeAverage()` - track sum/count, compute avg
|
|
18
|
+
- `mergeRate()` - track success/total, compute %
|
|
19
|
+
- `mergeMinMax()` - track min/max values
|
|
20
|
+
- Exported Zod schemas for internal state: `averageStateSchema`, `rateStateSchema`, `minMaxStateSchema`, `counterStateSchema`
|
|
21
|
+
|
|
22
|
+
### Improvements
|
|
23
|
+
|
|
24
|
+
- Enables O(1) storage overhead by maintaining incremental aggregation state
|
|
25
|
+
- Prepares for real-time hourly aggregation without batch accumulation
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [f676e11]
|
|
28
|
+
- Updated dependencies [48c2080]
|
|
29
|
+
- @checkstack/common@0.6.2
|
|
30
|
+
- @checkstack/backend-api@0.6.0
|
|
31
|
+
- @checkstack/healthcheck-common@0.8.2
|
|
32
|
+
|
|
3
33
|
## 0.1.13
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/healthcheck-dns-backend",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"scripts": {
|
|
@@ -9,14 +9,14 @@
|
|
|
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
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"@types/bun": "^1.0.0",
|
|
18
18
|
"typescript": "^5.0.0",
|
|
19
|
-
"@checkstack/tsconfig": "0.0.
|
|
20
|
-
"@checkstack/scripts": "0.1.
|
|
19
|
+
"@checkstack/tsconfig": "0.0.3",
|
|
20
|
+
"@checkstack/scripts": "0.1.1"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -4,7 +4,9 @@ import type { DnsTransportClient } from "./transport-client";
|
|
|
4
4
|
|
|
5
5
|
describe("LookupCollector", () => {
|
|
6
6
|
const createMockClient = (
|
|
7
|
-
response: { values: string[]; error?: string } = {
|
|
7
|
+
response: { values: string[]; error?: string } = {
|
|
8
|
+
values: ["192.168.1.1"],
|
|
9
|
+
},
|
|
8
10
|
): DnsTransportClient => ({
|
|
9
11
|
exec: mock(() => Promise.resolve(response)),
|
|
10
12
|
});
|
|
@@ -59,7 +61,7 @@ describe("LookupCollector", () => {
|
|
|
59
61
|
});
|
|
60
62
|
});
|
|
61
63
|
|
|
62
|
-
describe("
|
|
64
|
+
describe("mergeResult", () => {
|
|
63
65
|
it("should calculate average resolution time", () => {
|
|
64
66
|
const collector = new LookupCollector();
|
|
65
67
|
const runs = [
|
|
@@ -89,7 +91,9 @@ describe("LookupCollector", () => {
|
|
|
89
91
|
},
|
|
90
92
|
];
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
// Merge runs incrementally
|
|
95
|
+
let aggregated = collector.mergeResult(undefined, runs[0]);
|
|
96
|
+
aggregated = collector.mergeResult(aggregated, runs[1]);
|
|
93
97
|
|
|
94
98
|
expect(aggregated.avgResolutionTimeMs).toBe(75);
|
|
95
99
|
expect(aggregated.successRate).toBe(100);
|
|
@@ -120,7 +124,9 @@ describe("LookupCollector", () => {
|
|
|
120
124
|
},
|
|
121
125
|
];
|
|
122
126
|
|
|
123
|
-
|
|
127
|
+
// Merge runs incrementally
|
|
128
|
+
let aggregated = collector.mergeResult(undefined, runs[0]);
|
|
129
|
+
aggregated = collector.mergeResult(aggregated, runs[1]);
|
|
124
130
|
|
|
125
131
|
expect(aggregated.successRate).toBe(50);
|
|
126
132
|
});
|
package/src/lookup-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
|
+
averageStateSchema,
|
|
10
|
+
rateStateSchema,
|
|
11
|
+
type AverageState,
|
|
12
|
+
type RateState,
|
|
7
13
|
} from "@checkstack/backend-api";
|
|
8
14
|
import {
|
|
9
15
|
healthResultNumber,
|
|
@@ -50,7 +56,8 @@ const lookupResultSchema = healthResultSchema({
|
|
|
50
56
|
|
|
51
57
|
export type LookupResult = z.infer<typeof lookupResultSchema>;
|
|
52
58
|
|
|
53
|
-
|
|
59
|
+
// UI-visible aggregated fields (for charts)
|
|
60
|
+
const lookupAggregatedDisplaySchema = healthResultSchema({
|
|
54
61
|
avgResolutionTimeMs: healthResultNumber({
|
|
55
62
|
"x-chart-type": "line",
|
|
56
63
|
"x-chart-label": "Avg Resolution Time",
|
|
@@ -63,6 +70,17 @@ const lookupAggregatedSchema = healthResultSchema({
|
|
|
63
70
|
}),
|
|
64
71
|
});
|
|
65
72
|
|
|
73
|
+
// Internal state for incremental aggregation (not shown in charts)
|
|
74
|
+
const lookupAggregatedInternalSchema = z.object({
|
|
75
|
+
_resolutionTime: averageStateSchema.optional(),
|
|
76
|
+
_success: rateStateSchema.optional(),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Combined schema for storage
|
|
80
|
+
const lookupAggregatedSchema = lookupAggregatedDisplaySchema.merge(
|
|
81
|
+
lookupAggregatedInternalSchema,
|
|
82
|
+
);
|
|
83
|
+
|
|
66
84
|
export type LookupAggregatedResult = z.infer<typeof lookupAggregatedSchema>;
|
|
67
85
|
|
|
68
86
|
// ============================================================================
|
|
@@ -73,15 +91,12 @@ export type LookupAggregatedResult = z.infer<typeof lookupAggregatedSchema>;
|
|
|
73
91
|
* Built-in DNS lookup collector.
|
|
74
92
|
* Resolves DNS records and checks results.
|
|
75
93
|
*/
|
|
76
|
-
export class LookupCollector
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
LookupAggregatedResult
|
|
83
|
-
>
|
|
84
|
-
{
|
|
94
|
+
export class LookupCollector implements CollectorStrategy<
|
|
95
|
+
DnsTransportClient,
|
|
96
|
+
LookupConfig,
|
|
97
|
+
LookupResult,
|
|
98
|
+
LookupAggregatedResult
|
|
99
|
+
> {
|
|
85
100
|
id = "lookup";
|
|
86
101
|
displayName = "DNS Lookup";
|
|
87
102
|
description = "Resolve DNS records and check the results";
|
|
@@ -124,28 +139,30 @@ export class LookupCollector
|
|
|
124
139
|
};
|
|
125
140
|
}
|
|
126
141
|
|
|
127
|
-
|
|
128
|
-
|
|
142
|
+
mergeResult(
|
|
143
|
+
existing: LookupAggregatedResult | undefined,
|
|
144
|
+
run: HealthCheckRunForAggregation<LookupResult>,
|
|
129
145
|
): LookupAggregatedResult {
|
|
130
|
-
const
|
|
131
|
-
.map((r) => r.metadata?.resolutionTimeMs)
|
|
132
|
-
.filter((v): v is number => typeof v === "number");
|
|
146
|
+
const metadata = run.metadata;
|
|
133
147
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
148
|
+
// Merge resolution time average
|
|
149
|
+
const resolutionTimeState = mergeAverage(
|
|
150
|
+
existing?._resolutionTime as AverageState | undefined,
|
|
151
|
+
metadata?.resolutionTimeMs,
|
|
152
|
+
);
|
|
137
153
|
|
|
138
|
-
|
|
154
|
+
// Merge success rate (recordCount > 0 means success)
|
|
155
|
+
const isSuccess = (metadata?.recordCount ?? 0) > 0;
|
|
156
|
+
const successState = mergeRate(
|
|
157
|
+
existing?._success as RateState | undefined,
|
|
158
|
+
isSuccess,
|
|
159
|
+
);
|
|
139
160
|
|
|
140
161
|
return {
|
|
141
|
-
avgResolutionTimeMs:
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
successRate:
|
|
146
|
-
recordCounts.length > 0
|
|
147
|
-
? Math.round((successCount / recordCounts.length) * 100)
|
|
148
|
-
: 0,
|
|
162
|
+
avgResolutionTimeMs: resolutionTimeState.avg,
|
|
163
|
+
successRate: successState.rate,
|
|
164
|
+
_resolutionTime: resolutionTimeState,
|
|
165
|
+
_success: successState,
|
|
149
166
|
};
|
|
150
167
|
}
|
|
151
168
|
}
|
package/src/strategy.test.ts
CHANGED
|
@@ -15,7 +15,7 @@ describe("DnsHealthCheckStrategy", () => {
|
|
|
15
15
|
resolveMx?: { priority: number; exchange: string }[] | Error;
|
|
16
16
|
resolveTxt?: string[][] | Error;
|
|
17
17
|
resolveNs?: string[] | Error;
|
|
18
|
-
} = {}
|
|
18
|
+
} = {},
|
|
19
19
|
): ResolverFactory => {
|
|
20
20
|
return () =>
|
|
21
21
|
({
|
|
@@ -23,34 +23,34 @@ describe("DnsHealthCheckStrategy", () => {
|
|
|
23
23
|
resolve4: mock(() =>
|
|
24
24
|
config.resolve4 instanceof Error
|
|
25
25
|
? Promise.reject(config.resolve4)
|
|
26
|
-
: Promise.resolve(config.resolve4 ?? [])
|
|
26
|
+
: Promise.resolve(config.resolve4 ?? []),
|
|
27
27
|
),
|
|
28
28
|
resolve6: mock(() =>
|
|
29
29
|
config.resolve6 instanceof Error
|
|
30
30
|
? Promise.reject(config.resolve6)
|
|
31
|
-
: Promise.resolve(config.resolve6 ?? [])
|
|
31
|
+
: Promise.resolve(config.resolve6 ?? []),
|
|
32
32
|
),
|
|
33
33
|
resolveCname: mock(() =>
|
|
34
34
|
config.resolveCname instanceof Error
|
|
35
35
|
? Promise.reject(config.resolveCname)
|
|
36
|
-
: Promise.resolve(config.resolveCname ?? [])
|
|
36
|
+
: Promise.resolve(config.resolveCname ?? []),
|
|
37
37
|
),
|
|
38
38
|
resolveMx: mock(() =>
|
|
39
39
|
config.resolveMx instanceof Error
|
|
40
40
|
? Promise.reject(config.resolveMx)
|
|
41
|
-
: Promise.resolve(config.resolveMx ?? [])
|
|
41
|
+
: Promise.resolve(config.resolveMx ?? []),
|
|
42
42
|
),
|
|
43
43
|
resolveTxt: mock(() =>
|
|
44
44
|
config.resolveTxt instanceof Error
|
|
45
45
|
? Promise.reject(config.resolveTxt)
|
|
46
|
-
: Promise.resolve(config.resolveTxt ?? [])
|
|
46
|
+
: Promise.resolve(config.resolveTxt ?? []),
|
|
47
47
|
),
|
|
48
48
|
resolveNs: mock(() =>
|
|
49
49
|
config.resolveNs instanceof Error
|
|
50
50
|
? Promise.reject(config.resolveNs)
|
|
51
|
-
: Promise.resolve(config.resolveNs ?? [])
|
|
51
|
+
: Promise.resolve(config.resolveNs ?? []),
|
|
52
52
|
),
|
|
53
|
-
} as DnsResolver
|
|
53
|
+
}) as DnsResolver;
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
describe("createClient", () => {
|
|
@@ -102,7 +102,7 @@ describe("DnsHealthCheckStrategy", () => {
|
|
|
102
102
|
describe("client.exec", () => {
|
|
103
103
|
it("should return resolved values for successful A record resolution", async () => {
|
|
104
104
|
const strategy = new DnsHealthCheckStrategy(
|
|
105
|
-
createMockResolver({ resolve4: ["1.2.3.4", "5.6.7.8"] })
|
|
105
|
+
createMockResolver({ resolve4: ["1.2.3.4", "5.6.7.8"] }),
|
|
106
106
|
);
|
|
107
107
|
const connectedClient = await strategy.createClient({ timeout: 5000 });
|
|
108
108
|
|
|
@@ -118,7 +118,7 @@ describe("DnsHealthCheckStrategy", () => {
|
|
|
118
118
|
|
|
119
119
|
it("should return error for DNS error", async () => {
|
|
120
120
|
const strategy = new DnsHealthCheckStrategy(
|
|
121
|
-
createMockResolver({ resolve4: new Error("NXDOMAIN") })
|
|
121
|
+
createMockResolver({ resolve4: new Error("NXDOMAIN") }),
|
|
122
122
|
);
|
|
123
123
|
const connectedClient = await strategy.createClient({ timeout: 5000 });
|
|
124
124
|
|
|
@@ -139,7 +139,7 @@ describe("DnsHealthCheckStrategy", () => {
|
|
|
139
139
|
{ priority: 0, exchange: "mail1.example.com" },
|
|
140
140
|
{ priority: 10, exchange: "mail2.example.com" },
|
|
141
141
|
],
|
|
142
|
-
})
|
|
142
|
+
}),
|
|
143
143
|
);
|
|
144
144
|
const connectedClient = await strategy.createClient({ timeout: 5000 });
|
|
145
145
|
|
|
@@ -154,7 +154,7 @@ describe("DnsHealthCheckStrategy", () => {
|
|
|
154
154
|
});
|
|
155
155
|
});
|
|
156
156
|
|
|
157
|
-
describe("
|
|
157
|
+
describe("mergeResult", () => {
|
|
158
158
|
it("should calculate averages correctly", () => {
|
|
159
159
|
const strategy = new DnsHealthCheckStrategy();
|
|
160
160
|
const runs = [
|
|
@@ -184,7 +184,9 @@ describe("DnsHealthCheckStrategy", () => {
|
|
|
184
184
|
},
|
|
185
185
|
];
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
// Merge runs incrementally
|
|
188
|
+
let aggregated = strategy.mergeResult(undefined, runs[0]);
|
|
189
|
+
aggregated = strategy.mergeResult(aggregated, runs[1]);
|
|
188
190
|
|
|
189
191
|
expect(aggregated.avgResolutionTime).toBe(15);
|
|
190
192
|
expect(aggregated.failureCount).toBe(0);
|
|
@@ -221,7 +223,9 @@ describe("DnsHealthCheckStrategy", () => {
|
|
|
221
223
|
},
|
|
222
224
|
];
|
|
223
225
|
|
|
224
|
-
|
|
226
|
+
// Merge runs incrementally
|
|
227
|
+
let aggregated = strategy.mergeResult(undefined, runs[0]);
|
|
228
|
+
aggregated = strategy.mergeResult(aggregated, runs[1]);
|
|
225
229
|
|
|
226
230
|
expect(aggregated.errorCount).toBe(1);
|
|
227
231
|
expect(aggregated.failureCount).toBe(2);
|
package/src/strategy.ts
CHANGED
|
@@ -5,6 +5,12 @@ import {
|
|
|
5
5
|
Versioned,
|
|
6
6
|
z,
|
|
7
7
|
type ConnectedClient,
|
|
8
|
+
mergeCounter,
|
|
9
|
+
mergeAverage,
|
|
10
|
+
averageStateSchema,
|
|
11
|
+
counterStateSchema,
|
|
12
|
+
type CounterState,
|
|
13
|
+
type AverageState,
|
|
8
14
|
} from "@checkstack/backend-api";
|
|
9
15
|
import {
|
|
10
16
|
healthResultNumber,
|
|
@@ -73,7 +79,8 @@ type DnsResult = z.infer<typeof dnsResultSchema>;
|
|
|
73
79
|
/**
|
|
74
80
|
* Aggregated metadata for buckets.
|
|
75
81
|
*/
|
|
76
|
-
|
|
82
|
+
// UI-visible aggregated fields (for charts)
|
|
83
|
+
const dnsAggregatedDisplaySchema = healthResultSchema({
|
|
77
84
|
avgResolutionTime: healthResultNumber({
|
|
78
85
|
"x-chart-type": "line",
|
|
79
86
|
"x-chart-label": "Avg Resolution Time",
|
|
@@ -89,6 +96,18 @@ const dnsAggregatedSchema = healthResultSchema({
|
|
|
89
96
|
}),
|
|
90
97
|
});
|
|
91
98
|
|
|
99
|
+
// Internal state for incremental aggregation (not shown in charts)
|
|
100
|
+
const dnsAggregatedInternalSchema = z.object({
|
|
101
|
+
_resolutionTime: averageStateSchema.optional(),
|
|
102
|
+
_failures: counterStateSchema.optional(),
|
|
103
|
+
_errors: counterStateSchema.optional(),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Combined schema for storage
|
|
107
|
+
const dnsAggregatedSchema = dnsAggregatedDisplaySchema.merge(
|
|
108
|
+
dnsAggregatedInternalSchema,
|
|
109
|
+
);
|
|
110
|
+
|
|
92
111
|
type DnsAggregatedResult = z.infer<typeof dnsAggregatedSchema>;
|
|
93
112
|
|
|
94
113
|
// ============================================================================
|
|
@@ -101,7 +120,7 @@ export interface DnsResolver {
|
|
|
101
120
|
resolve6(hostname: string): Promise<string[]>;
|
|
102
121
|
resolveCname(hostname: string): Promise<string[]>;
|
|
103
122
|
resolveMx(
|
|
104
|
-
hostname: string
|
|
123
|
+
hostname: string,
|
|
105
124
|
): Promise<{ priority: number; exchange: string }[]>;
|
|
106
125
|
resolveTxt(hostname: string): Promise<string[][]>;
|
|
107
126
|
resolveNs(hostname: string): Promise<string[]>;
|
|
@@ -116,15 +135,12 @@ const defaultResolverFactory: ResolverFactory = () => new dns.Resolver();
|
|
|
116
135
|
// STRATEGY
|
|
117
136
|
// ============================================================================
|
|
118
137
|
|
|
119
|
-
export class DnsHealthCheckStrategy
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
DnsAggregatedResult
|
|
126
|
-
>
|
|
127
|
-
{
|
|
138
|
+
export class DnsHealthCheckStrategy implements HealthCheckStrategy<
|
|
139
|
+
DnsConfig,
|
|
140
|
+
DnsTransportClient,
|
|
141
|
+
DnsResult,
|
|
142
|
+
DnsAggregatedResult
|
|
143
|
+
> {
|
|
128
144
|
id = "dns";
|
|
129
145
|
displayName = "DNS Health Check";
|
|
130
146
|
description = "DNS record resolution with response validation";
|
|
@@ -169,39 +185,44 @@ export class DnsHealthCheckStrategy
|
|
|
169
185
|
schema: dnsAggregatedSchema,
|
|
170
186
|
});
|
|
171
187
|
|
|
172
|
-
|
|
173
|
-
|
|
188
|
+
mergeResult(
|
|
189
|
+
existing: DnsAggregatedResult | undefined,
|
|
190
|
+
run: HealthCheckRunForAggregation<DnsResult>,
|
|
174
191
|
): DnsAggregatedResult {
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
192
|
+
const metadata = run.metadata;
|
|
193
|
+
|
|
194
|
+
// Merge resolution time average
|
|
195
|
+
const resolutionTimeState = mergeAverage(
|
|
196
|
+
existing?._resolutionTime as AverageState | undefined,
|
|
197
|
+
metadata?.resolutionTimeMs,
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
// Merge failure count (recordCount === 0 means failure)
|
|
201
|
+
const isFailure = metadata?.recordCount === 0;
|
|
202
|
+
const failureState = mergeCounter(
|
|
203
|
+
existing?._failures as CounterState | undefined,
|
|
204
|
+
isFailure,
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
// Merge error count
|
|
208
|
+
const hasError = metadata?.error !== undefined;
|
|
209
|
+
const errorState = mergeCounter(
|
|
210
|
+
existing?._errors as CounterState | undefined,
|
|
211
|
+
hasError,
|
|
212
|
+
);
|
|
180
213
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
)
|
|
190
|
-
: 0;
|
|
191
|
-
|
|
192
|
-
const failureCount = validRuns.filter(
|
|
193
|
-
(r) => r.metadata?.recordCount === 0
|
|
194
|
-
).length;
|
|
195
|
-
|
|
196
|
-
const errorCount = validRuns.filter(
|
|
197
|
-
(r) => r.metadata?.error !== undefined
|
|
198
|
-
).length;
|
|
199
|
-
|
|
200
|
-
return { avgResolutionTime, failureCount, errorCount };
|
|
214
|
+
return {
|
|
215
|
+
avgResolutionTime: resolutionTimeState.avg,
|
|
216
|
+
failureCount: failureState.count,
|
|
217
|
+
errorCount: errorState.count,
|
|
218
|
+
_resolutionTime: resolutionTimeState,
|
|
219
|
+
_failures: failureState,
|
|
220
|
+
_errors: errorState,
|
|
221
|
+
};
|
|
201
222
|
}
|
|
202
223
|
|
|
203
224
|
async createClient(
|
|
204
|
-
config: DnsConfig
|
|
225
|
+
config: DnsConfig,
|
|
205
226
|
): Promise<ConnectedClient<DnsTransportClient>> {
|
|
206
227
|
const validatedConfig = this.config.validate(config);
|
|
207
228
|
const resolver = this.resolverFactory();
|
|
@@ -214,14 +235,17 @@ export class DnsHealthCheckStrategy
|
|
|
214
235
|
exec: async (request: DnsLookupRequest): Promise<DnsLookupResult> => {
|
|
215
236
|
const timeout = validatedConfig.timeout;
|
|
216
237
|
const timeoutPromise = new Promise<never>((_, reject) =>
|
|
217
|
-
setTimeout(
|
|
238
|
+
setTimeout(
|
|
239
|
+
() => reject(new Error("DNS resolution timeout")),
|
|
240
|
+
timeout,
|
|
241
|
+
),
|
|
218
242
|
);
|
|
219
243
|
|
|
220
244
|
try {
|
|
221
245
|
const resolvePromise = this.resolveRecords(
|
|
222
246
|
resolver,
|
|
223
247
|
request.hostname,
|
|
224
|
-
request.recordType
|
|
248
|
+
request.recordType,
|
|
225
249
|
);
|
|
226
250
|
|
|
227
251
|
const values = await Promise.race([resolvePromise, timeoutPromise]);
|
|
@@ -246,7 +270,7 @@ export class DnsHealthCheckStrategy
|
|
|
246
270
|
private async resolveRecords(
|
|
247
271
|
resolver: DnsResolver,
|
|
248
272
|
hostname: string,
|
|
249
|
-
recordType: "A" | "AAAA" | "CNAME" | "MX" | "TXT" | "NS"
|
|
273
|
+
recordType: "A" | "AAAA" | "CNAME" | "MX" | "TXT" | "NS",
|
|
250
274
|
): Promise<string[]> {
|
|
251
275
|
switch (recordType) {
|
|
252
276
|
case "A": {
|