Merge pull request #3696 from bluewave-labs/fix/connection-reuse

fix: connection reuse
This commit is contained in:
Alexander Holliday authored and GitHub committed 2026-06-03 11:54:33 -07:00
commit ddd937d42f
2 files changed
+21 -9

No files matched your search

@@ -4,6 +4,7 @@ import { IStatusProvider } from "@/service/infrastructure/network/IStatusProvide
import { HttpStatusPayload } from "@/types/network.js";
import { MonitorStatusResponse } from "@/types/network.js";
import { Agent as HttpsAgent } from "https";
import { Agent as HttpAgent } from "http";
import { Monitor, MonitorType } from "@/types/monitor.js";
import { NETWORK_ERROR } from "@/service/infrastructure/network/utils.js";
import CacheableLookup from "cacheable-lookup";
@@ -11,6 +12,11 @@ import CacheableLookup from "cacheable-lookup";
export class HttpProvider implements IStatusProvider<HttpStatusPayload> {
readonly type = "http";
// Shared, pooled agents reused across every check
private readonly httpAgent: HttpAgent;
private readonly httpsAgent: HttpsAgent;
private readonly httpsAgentInsecure: HttpsAgent;
constructor(
private got: Got,
private advancedMatcher: IAdvancedMatcher
@@ -23,6 +29,11 @@ export class HttpProvider implements IStatusProvider<HttpStatusPayload> {
},
retry: { limit: 1 },
});
const agentOptions = { keepAlive: true, maxSockets: 256, maxFreeSockets: 256 };
this.httpAgent = new HttpAgent(agentOptions);
this.httpsAgent = new HttpsAgent({ ...agentOptions, rejectUnauthorized: true });
this.httpsAgentInsecure = new HttpsAgent({ ...agentOptions, rejectUnauthorized: false });
}
supports(type: MonitorType) {
@@ -38,7 +49,7 @@ export class HttpProvider implements IStatusProvider<HttpStatusPayload> {
status: false,
code: error.response?.statusCode ?? NETWORK_ERROR,
message: error.message,
responseTime: error.timings?.phases?.total ?? 0,
responseTime: error.timings?.phases?.firstByte ?? error.timings?.phases?.total ?? 0,
timings: error.timings,
payload: null as T,
};
@@ -68,7 +79,8 @@ export class HttpProvider implements IStatusProvider<HttpStatusPayload> {
};
options.agent = {
https: new HttpsAgent({ rejectUnauthorized: !ignoreTlsErrors }),
http: this.httpAgent,
https: ignoreTlsErrors ? this.httpsAgentInsecure : this.httpsAgent,
};
try {
@@ -84,7 +96,7 @@ export class HttpProvider implements IStatusProvider<HttpStatusPayload> {
status: false,
code: response.statusCode,
message: "Response is not JSON",
responseTime: response.timings.phases.total ?? 0,
responseTime: response.timings.phases.firstByte ?? 0,
timings: response.timings,
payload: response.body as unknown as T,
};
@@ -109,7 +121,7 @@ export class HttpProvider implements IStatusProvider<HttpStatusPayload> {
status: response.ok && matchResult.ok,
code: response.statusCode,
message: matchResult.ok ? (response.statusMessage ?? "OK") : matchResult.message,
responseTime: response.timings.phases.total ?? 0,
responseTime: response.timings.phases.firstByte ?? 0,
timings: response.timings,
payload,
extracted: matchResult.extracted,
@@ -69,7 +69,7 @@ const makeGotResponse = (overrides?: Record<string, any>) => ({
statusMessage: "OK",
headers: { "content-type": "text/html" },
body: "<html></html>",
timings: { phases: { total: 100 } },
timings: { phases: { firstByte: 100, total: 120 } },
...overrides,
});
@@ -181,8 +181,8 @@ describe("HttpProvider", () => {
);
});
it("defaults responseTime to 0 when timings.phases.total is undefined", async () => {
mockGot.mockResolvedValue(makeGotResponse({ timings: { phases: { total: undefined } } }));
it("defaults responseTime to 0 when timings.phases.firstByte is undefined", async () => {
mockGot.mockResolvedValue(makeGotResponse({ timings: { phases: { firstByte: undefined } } }));
const { provider } = createProvider();
const result = await provider.handle(makeMonitor());
@@ -223,11 +223,11 @@ describe("HttpProvider", () => {
expect(result.message).toBe("Response is not JSON");
});
it("defaults responseTime to 0 in non-JSON jsonPath response when total is undefined", async () => {
it("defaults responseTime to 0 in non-JSON jsonPath response when firstByte is undefined", async () => {
mockGot.mockResolvedValue(
makeGotResponse({
headers: { "content-type": "text/html" },
timings: { phases: { total: undefined } },
timings: { phases: { firstByte: undefined } },
})
);
const { provider } = createProvider();