per call resolver
This commit is contained in:
1 parent
0f662e1a65
commit
fc711e8e24
3 files changed
+30
-35
No files matched your search
@@ -228,7 +228,7 @@ export const initializeServices = async ({
|
||||
const gameProvider = new GameProvider(logger, GameDig);
|
||||
const grpcProvider = new GrpcProvider(grpc, protoLoader);
|
||||
const webSocketProvider = new WebSocketProvider(WebSocket);
|
||||
const dnsProvider = new DNSProvider(new Resolver());
|
||||
const dnsProvider = new DNSProvider(() => new Resolver());
|
||||
|
||||
const networkService = new NetworkService(axios, logger, [
|
||||
pingProvider,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DNSStatusPayload, MonitorStatusResponse } from "@/types/network.js";
|
||||
import { IStatusProvider } from "@/service/infrastructure/network/IStatusProvider.js";
|
||||
import { Resolver } from "dns/promises";
|
||||
import type { Resolver } from "dns/promises";
|
||||
import { Monitor, MonitorType } from "@/types/monitor.js";
|
||||
import { AppError } from "@/utils/AppError.js";
|
||||
import { NETWORK_ERROR, timeRequest } from "@/service/infrastructure/network/utils.js";
|
||||
@@ -9,7 +9,7 @@ const SERVICE_NAME = "DNSProvider";
|
||||
|
||||
export class DNSProvider implements IStatusProvider<DNSStatusPayload> {
|
||||
readonly type = "dns";
|
||||
constructor(private resolver: Resolver) {}
|
||||
constructor(private createResolver: () => Resolver) {}
|
||||
supports(type: MonitorType) {
|
||||
return type === "dns";
|
||||
}
|
||||
@@ -21,7 +21,8 @@ export class DNSProvider implements IStatusProvider<DNSStatusPayload> {
|
||||
throw new Error("DNS server is required for DNS monitoring");
|
||||
}
|
||||
|
||||
this.resolver.setServers([dnsServer]);
|
||||
const resolver = this.createResolver();
|
||||
resolver.setServers([dnsServer]);
|
||||
|
||||
const {
|
||||
response: results,
|
||||
@@ -30,19 +31,19 @@ export class DNSProvider implements IStatusProvider<DNSStatusPayload> {
|
||||
} = await timeRequest(() => {
|
||||
switch (dnsRecordType.toUpperCase()) {
|
||||
case "A":
|
||||
return this.resolver.resolve4(hostname);
|
||||
return resolver.resolve4(hostname);
|
||||
case "AAAA":
|
||||
return this.resolver.resolve6(hostname);
|
||||
return resolver.resolve6(hostname);
|
||||
case "CNAME":
|
||||
return this.resolver.resolveCname(hostname);
|
||||
return resolver.resolveCname(hostname);
|
||||
case "MX":
|
||||
return this.resolver.resolveMx(hostname);
|
||||
return resolver.resolveMx(hostname);
|
||||
case "TXT":
|
||||
return this.resolver.resolveTxt(hostname);
|
||||
return resolver.resolveTxt(hostname);
|
||||
case "NS":
|
||||
return this.resolver.resolveNs(hostname);
|
||||
return resolver.resolveNs(hostname);
|
||||
default:
|
||||
return this.resolver.resolve(hostname, dnsRecordType);
|
||||
return resolver.resolve(hostname, dnsRecordType);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, jest } from "@jest/globals";
|
||||
import { testStatusProviderContract } from "../../../helpers/statusProviderContract.ts";
|
||||
import { NETWORK_ERROR } from "../../../../src/service/infrastructure/network/utils.ts";
|
||||
import type { Monitor } from "../../../../src/types/index.ts";
|
||||
import { DNSProvider } from "../../../../src/service/infrastructure/network/DNSProvider.ts";
|
||||
|
||||
// ── Mocks ────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -16,13 +17,7 @@ const mockResolverInstance = {
|
||||
resolve: jest.fn<() => Promise<unknown>>(),
|
||||
};
|
||||
|
||||
const ResolverMock = jest.fn().mockImplementation(() => mockResolverInstance);
|
||||
|
||||
jest.unstable_mockModule("dns/promises", () => ({
|
||||
Resolver: ResolverMock,
|
||||
}));
|
||||
|
||||
const { DNSProvider } = await import("../../../../src/service/infrastructure/network/DNSProvider.ts");
|
||||
const createResolver = () => mockResolverInstance as any;
|
||||
|
||||
// ── Helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -38,7 +33,6 @@ const makeMonitor = (overrides?: Partial<Monitor>): Monitor =>
|
||||
}) as Monitor;
|
||||
|
||||
beforeEach(() => {
|
||||
ResolverMock.mockClear();
|
||||
mockResolverInstance.setServers.mockClear();
|
||||
mockResolverInstance.resolve4.mockReset().mockResolvedValue(["1.2.3.4"]);
|
||||
mockResolverInstance.resolve6.mockReset().mockResolvedValue(["::1"]);
|
||||
@@ -52,7 +46,7 @@ beforeEach(() => {
|
||||
// ── Contract ─────────────────────────────────────────────────────────────────
|
||||
|
||||
testStatusProviderContract("DNSProvider", {
|
||||
create: () => new DNSProvider(mockResolverInstance as any),
|
||||
create: () => new DNSProvider(createResolver),
|
||||
supportedType: "dns",
|
||||
unsupportedType: "ping",
|
||||
makeMonitor: () => makeMonitor(),
|
||||
@@ -63,7 +57,7 @@ testStatusProviderContract("DNSProvider", {
|
||||
describe("DNSProvider", () => {
|
||||
it("returns success with results and payload on resolve", async () => {
|
||||
mockResolverInstance.resolve4.mockResolvedValue(["1.2.3.4"]);
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
|
||||
const result = await provider.handle(makeMonitor());
|
||||
|
||||
@@ -88,63 +82,63 @@ describe("DNSProvider", () => {
|
||||
});
|
||||
|
||||
it("calls setServers with the configured dnsServer", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
await provider.handle(makeMonitor({ dnsServer: "1.1.1.1" }));
|
||||
expect(mockResolverInstance.setServers).toHaveBeenCalledWith(["1.1.1.1"]);
|
||||
});
|
||||
|
||||
it("defaults to A record when dnsRecordType is not provided", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
const result = await provider.handle(makeMonitor({ dnsRecordType: undefined }));
|
||||
expect(mockResolverInstance.resolve4).toHaveBeenCalledWith("example.com");
|
||||
expect(result.payload?.recordType).toBe("A");
|
||||
});
|
||||
|
||||
it("dispatches AAAA records to resolve6", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
await provider.handle(makeMonitor({ dnsRecordType: "AAAA" }));
|
||||
expect(mockResolverInstance.resolve6).toHaveBeenCalledWith("example.com");
|
||||
});
|
||||
|
||||
it("dispatches CNAME records to resolveCname", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
await provider.handle(makeMonitor({ dnsRecordType: "CNAME" }));
|
||||
expect(mockResolverInstance.resolveCname).toHaveBeenCalledWith("example.com");
|
||||
});
|
||||
|
||||
it("dispatches MX records to resolveMx", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
await provider.handle(makeMonitor({ dnsRecordType: "MX" }));
|
||||
expect(mockResolverInstance.resolveMx).toHaveBeenCalledWith("example.com");
|
||||
});
|
||||
|
||||
it("dispatches TXT records to resolveTxt", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
await provider.handle(makeMonitor({ dnsRecordType: "TXT" }));
|
||||
expect(mockResolverInstance.resolveTxt).toHaveBeenCalledWith("example.com");
|
||||
});
|
||||
|
||||
it("dispatches NS records to resolveNs", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
await provider.handle(makeMonitor({ dnsRecordType: "NS" }));
|
||||
expect(mockResolverInstance.resolveNs).toHaveBeenCalledWith("example.com");
|
||||
});
|
||||
|
||||
it("falls back to generic resolve for unrecognized record types", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
await provider.handle(makeMonitor({ dnsRecordType: "SOA" }));
|
||||
expect(mockResolverInstance.resolve).toHaveBeenCalledWith("example.com", "SOA");
|
||||
});
|
||||
|
||||
it("treats record type case-insensitively", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
await provider.handle(makeMonitor({ dnsRecordType: "mx" }));
|
||||
expect(mockResolverInstance.resolveMx).toHaveBeenCalledWith("example.com");
|
||||
});
|
||||
|
||||
it("returns failure response with NETWORK_ERROR when resolver rejects", async () => {
|
||||
mockResolverInstance.resolve4.mockRejectedValue(new Error("ENOTFOUND"));
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
|
||||
const result = await provider.handle(makeMonitor());
|
||||
|
||||
@@ -170,7 +164,7 @@ describe("DNSProvider", () => {
|
||||
|
||||
it("stringifies non-Error rejections in failure response", async () => {
|
||||
mockResolverInstance.resolve4.mockRejectedValue("DNS bombed");
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
|
||||
const result = await provider.handle(makeMonitor());
|
||||
|
||||
@@ -179,7 +173,7 @@ describe("DNSProvider", () => {
|
||||
});
|
||||
|
||||
it("throws AppError when dnsServer is missing", async () => {
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
|
||||
await expect(provider.handle(makeMonitor({ dnsServer: undefined }))).rejects.toThrow("DNS server is required for DNS monitoring");
|
||||
});
|
||||
@@ -188,7 +182,7 @@ describe("DNSProvider", () => {
|
||||
mockResolverInstance.setServers.mockImplementationOnce(() => {
|
||||
throw new Error("");
|
||||
});
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
|
||||
await expect(provider.handle(makeMonitor())).rejects.toThrow("Error performing DNS check");
|
||||
});
|
||||
@@ -197,7 +191,7 @@ describe("DNSProvider", () => {
|
||||
mockResolverInstance.setServers.mockImplementationOnce(() => {
|
||||
throw 42;
|
||||
});
|
||||
const provider = new DNSProvider(mockResolverInstance as any);
|
||||
const provider = new DNSProvider(createResolver);
|
||||
|
||||
await expect(provider.handle(makeMonitor())).rejects.toThrow("42");
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user