wire up proxy resolver
This commit is contained in:
1 parent
ffd7ea7517
commit
1152a70afb
7 files changed
+65
-11
No files matched your search
@@ -26,7 +26,7 @@ import { NotificationReactor } from "@/worker/reactors/reactor.notification.js";
|
||||
import { IncidentReactor } from "@/worker/reactors/reactor.incident.js";
|
||||
import { ReactorDispatcher } from "@/worker/reactors/reactor.dispatcher.js";
|
||||
import { DBQueueWorker } from "@/worker/worker.db-queue.js";
|
||||
|
||||
import { ProxyResolver } from "@/service/network/ProxyResolver.js";
|
||||
// Network providers
|
||||
import { PingProvider } from "@/service/network/PingProvider.js";
|
||||
import { HttpProvider } from "@/service/network/HttpProvider.js";
|
||||
@@ -64,6 +64,7 @@ export const buildWorker = async (shared: SharedServices, envSettings: EnvConfig
|
||||
incidentsRepository,
|
||||
teamsRepository,
|
||||
maintenanceWindowsRepository,
|
||||
proxiesRepository,
|
||||
} = shared;
|
||||
|
||||
// ***********************
|
||||
@@ -93,6 +94,7 @@ export const buildWorker = async (shared: SharedServices, envSettings: EnvConfig
|
||||
dnsProvider,
|
||||
]);
|
||||
|
||||
const proxyResolver = new ProxyResolver(proxiesRepository, settingsService, logger);
|
||||
const bufferService = new BufferService(logger, checkService, geoChecksService, settingsService, jobsRepository);
|
||||
const statusService = new StatusService(logger, monitorsRepository, monitorStatsRepository);
|
||||
const monitorStatusPolicy = new MonitorStatusPolicy();
|
||||
@@ -110,7 +112,15 @@ export const buildWorker = async (shared: SharedServices, envSettings: EnvConfig
|
||||
// Check producer/evaluator
|
||||
// Handles creating and evaluatiog checks
|
||||
// ***********************
|
||||
const checkProducer = new CheckProducer(monitorsRepository, maintenanceWindowsRepository, checkService, networkService, bufferService, logger);
|
||||
const checkProducer = new CheckProducer(
|
||||
monitorsRepository,
|
||||
maintenanceWindowsRepository,
|
||||
checkService,
|
||||
networkService,
|
||||
proxyResolver,
|
||||
bufferService,
|
||||
logger
|
||||
);
|
||||
const checkEvaluator = new CheckEvaluator(statusService, monitorStatusPolicy);
|
||||
const geoCheckPipeline = new GeoChecksPipeline(maintenanceWindowsRepository, geoChecksService, bufferService, logger);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js";
|
||||
import { MonitorStatusResponse } from "@/types/network.js";
|
||||
|
||||
import { CheckContext } from "@/types/network.js";
|
||||
export interface IStatusProvider<T> {
|
||||
type: string;
|
||||
supports: (type: MonitorType) => boolean;
|
||||
handle(monitor: Monitor): Promise<MonitorStatusResponse<T>>;
|
||||
handle(monitor: Monitor, ctx?: CheckContext): Promise<MonitorStatusResponse<T>>;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Monitor, MonitorType } from "@/domain/monitors/monitor.type.js";
|
||||
import type { MonitorPayloadMap, MonitorStatusResponse } from "@/types/network.js";
|
||||
import type { CheckContext, MonitorPayloadMap, MonitorStatusResponse } from "@/types/network.js";
|
||||
import type { AxiosStatic } from "axios";
|
||||
import { AppError } from "@/utils/AppError.js";
|
||||
import { NETWORK_ERROR } from "@/types/network.js";
|
||||
@@ -8,7 +8,7 @@ import { IStatusProvider } from "./network/IStatusProvider.js";
|
||||
const SERVICE_NAME = "NetworkService";
|
||||
|
||||
export interface INetworkService {
|
||||
requestStatus<T extends MonitorType>(monitor: Monitor & { type: T }): Promise<MonitorStatusResponse<MonitorPayloadMap[T]>>;
|
||||
requestStatus<T extends MonitorType>(monitor: Monitor & { type: T }, ctx?: CheckContext): Promise<MonitorStatusResponse<MonitorPayloadMap[T]>>;
|
||||
requestWebhook(
|
||||
type: string,
|
||||
url: string,
|
||||
@@ -39,12 +39,15 @@ export class NetworkService implements INetworkService {
|
||||
}
|
||||
|
||||
// Main entry point
|
||||
async requestStatus<T extends MonitorType>(monitor: Monitor & { type: T }): Promise<MonitorStatusResponse<MonitorPayloadMap[T]>> {
|
||||
async requestStatus<T extends MonitorType>(
|
||||
monitor: Monitor & { type: T },
|
||||
ctx?: CheckContext
|
||||
): Promise<MonitorStatusResponse<MonitorPayloadMap[T]>> {
|
||||
const provider = this.providers.find((p) => p.supports(monitor.type));
|
||||
if (!provider) {
|
||||
return this.handleUnsupportedType(monitor.type) as Promise<MonitorStatusResponse<MonitorPayloadMap[T]>>;
|
||||
}
|
||||
return provider.handle(monitor) as Promise<MonitorStatusResponse<MonitorPayloadMap[T]>>;
|
||||
return provider.handle(monitor, ctx) as Promise<MonitorStatusResponse<MonitorPayloadMap[T]>>;
|
||||
}
|
||||
|
||||
private async handleUnsupportedType(type: string): Promise<MonitorStatusResponse> {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { ICheckService } from "@/domain/checks/check.service.js";
|
||||
import { IMonitorsRepository } from "@/domain/monitors/monitor.repository.interface.js";
|
||||
import { IMaintenanceWindowsRepository } from "@/domain/maintenance-windows/maintenance-window.repository.interface.js";
|
||||
import { isWindowActive } from "@/utils/maintenanceWindow.js";
|
||||
import { IProxyResolver } from "@/service/network/ProxyResolver.js";
|
||||
|
||||
export interface ICheckProducer {
|
||||
produce(monitor: Monitor): Promise<{ status: MonitorStatusResponse; check: Check } | null>;
|
||||
@@ -22,6 +23,7 @@ export class CheckProducer implements ICheckProducer {
|
||||
private maintenanceWindowsRepository: IMaintenanceWindowsRepository,
|
||||
private checkService: ICheckService,
|
||||
private networkService: INetworkService,
|
||||
private proxyResolver: IProxyResolver,
|
||||
private bufferService: IBufferService,
|
||||
private logger: ILogger
|
||||
) {}
|
||||
@@ -56,7 +58,8 @@ export class CheckProducer implements ICheckProducer {
|
||||
}
|
||||
|
||||
// Step 1b: Acquire status
|
||||
const status = await this.networkService.requestStatus(monitor);
|
||||
const proxyUrl = await this.proxyResolver.resolve(monitor);
|
||||
const status = await this.networkService.requestStatus(monitor, { proxyUrl });
|
||||
if (!status) {
|
||||
throw new Error("No network response");
|
||||
}
|
||||
|
||||
@@ -127,12 +127,14 @@ export function createHeartbeatTestHarness(): HeartbeatTestHarness {
|
||||
};
|
||||
|
||||
const maintenanceWindowsRepo = { findByMonitorId: jest.fn().mockResolvedValue([]) };
|
||||
const proxyResolver = { resolve: jest.fn().mockResolvedValue(undefined) };
|
||||
|
||||
const checkProducer = new CheckProducer(
|
||||
monitorsRepo as any,
|
||||
maintenanceWindowsRepo as any,
|
||||
checkService as any,
|
||||
networkService as any,
|
||||
proxyResolver as any,
|
||||
bufferStub as any,
|
||||
logger
|
||||
);
|
||||
|
||||
@@ -26,6 +26,7 @@ const createProducer = (overrides?: Record<string, any>) => {
|
||||
maintenanceWindowsRepository: { findByMonitorId: jest.fn().mockResolvedValue([]) },
|
||||
checkService: { toCheck: jest.fn().mockReturnValue({ id: "check-1" }) },
|
||||
networkService: { requestStatus: jest.fn().mockResolvedValue({ monitorId: "m1", status: true, code: 200, message: "OK" }) },
|
||||
proxyResolver: { resolve: jest.fn().mockResolvedValue(undefined) },
|
||||
buffer: { addToBuffer: jest.fn() },
|
||||
...overrides,
|
||||
};
|
||||
@@ -34,6 +35,7 @@ const createProducer = (overrides?: Record<string, any>) => {
|
||||
defaults.maintenanceWindowsRepository as any,
|
||||
defaults.checkService as any,
|
||||
defaults.networkService as any,
|
||||
defaults.proxyResolver as any,
|
||||
defaults.buffer as any,
|
||||
defaults.logger as any
|
||||
);
|
||||
@@ -82,6 +84,29 @@ describe("CheckProducer", () => {
|
||||
expect(defaults.networkService.requestStatus).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
// ── proxy resolution ──────────────────────────────────────────────────────
|
||||
|
||||
it("passes the resolved proxy url into requestStatus", async () => {
|
||||
const { producer, defaults } = createProducer({
|
||||
proxyResolver: { resolve: jest.fn().mockResolvedValue("http://proxy.example.com:8080") },
|
||||
});
|
||||
const monitor = makeMonitor();
|
||||
|
||||
await producer.produce(monitor);
|
||||
|
||||
expect(defaults.networkService.requestStatus).toHaveBeenCalledWith(monitor, { proxyUrl: "http://proxy.example.com:8080" });
|
||||
});
|
||||
|
||||
it("still produces a check when the resolver returns undefined", async () => {
|
||||
const { producer, defaults } = createProducer();
|
||||
const monitor = makeMonitor();
|
||||
|
||||
const result = await producer.produce(monitor);
|
||||
|
||||
expect(defaults.networkService.requestStatus).toHaveBeenCalledWith(monitor, { proxyUrl: undefined });
|
||||
expect(result).toEqual({ status: expect.objectContaining({ monitorId: "m1" }), check: { id: "check-1" } });
|
||||
});
|
||||
|
||||
// ── acquire / record ──────────────────────────────────────────────────────
|
||||
|
||||
it("throws when the network response is null", async () => {
|
||||
|
||||
@@ -54,7 +54,7 @@ describe("NetworkService", () => {
|
||||
const result = await service.requestStatus(monitor);
|
||||
|
||||
expect(provider.supports).toHaveBeenCalledWith("http");
|
||||
expect(provider.handle).toHaveBeenCalledWith(monitor);
|
||||
expect(provider.handle).toHaveBeenCalledWith(monitor, undefined);
|
||||
expect(result).toEqual(
|
||||
expect.objectContaining({
|
||||
monitorId: "mon-1",
|
||||
@@ -73,7 +73,18 @@ describe("NetworkService", () => {
|
||||
await service.requestStatus(monitor);
|
||||
|
||||
expect(httpProvider.handle).not.toHaveBeenCalled();
|
||||
expect(pingProvider.handle).toHaveBeenCalledWith(monitor);
|
||||
expect(pingProvider.handle).toHaveBeenCalledWith(monitor, undefined);
|
||||
});
|
||||
|
||||
it("forwards the check context to the provider", async () => {
|
||||
const provider = createMockProvider("http");
|
||||
const { service } = createService([provider]);
|
||||
const monitor = { type: "http", _id: "mon-1" } as unknown as Monitor & { type: "http" };
|
||||
const ctx = { proxyUrl: "http://proxy.example.com:8080" };
|
||||
|
||||
await service.requestStatus(monitor, ctx);
|
||||
|
||||
expect(provider.handle).toHaveBeenCalledWith(monitor, ctx);
|
||||
});
|
||||
|
||||
it("returns unsupported-type response when no provider matches", async () => {
|
||||
|
||||
Reference in new issue
Block a user