Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Floxy residential proxy bitince/çökünce (402 bakiye veya tünel reddi — ERR_TUNNEL_CONNECTION_FAILED), EMEX + pcat decode istekleri ölü proxy'ye çarpıp decode başarı oranını çökertiyordu (2026-06-13: ~17k tünel hatası/24s, decode %78→%45). Önceki "DataImpulse last-ditch fallback" tarayıcı yolunda hiç yoktu ve HTTP yolunda her istekte 2 ölü Floxy denemesi ziyan ediyordu. Paylaşılan ProxyHealthService kapısı (in-memory cooldown): herhangi bir tüketici bir Floxy bağlantı hatası görünce kapıyı tetikler; cooldown boyunca TÜM tüketiciler DataImpulse'a düşer. Floxy'den ilk başarılı yanıt veya cooldown bitişi kapıyı temizler (kendi kendini iyileştirir, periyodik yeniden-deneme). FLOXY_FAILOVER_COOLDOWN_MS ile ayarlanır (varsayılan 180s). Bağlanan tüketiciler: - EMEX HTTP (fetchEmexHtml): kapı açıkken DataImpulse-öncelikli zamanlama - EMEX tarayıcı (Playwright): launch'ta dinamik sağlayıcı seçimi + ensureSession health-gate'i (Floxy ölünce DataImpulse'a relaunch, kapı temizlenince Floxy'i yeniden dene); scrape-içi tünel ölümünde tripFloxyFailover - pcat (buildProxy): hem call hem capture (Playwright JWT) bacakları DataImpulse'a düşer isProxyConnectFailure(): yalnız gerçek bağlantı hatalarında tetikler — yavaş-ama- canlı exit'in nav timeout'u failover'ı tetiklemez. Test: ProxyHealthService + isProxyConnectFailure birim testleri; tüm api suite (303) yeşil. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
import type { ConfigService } from "@nestjs/config";
|
|
import { describe, expect, it, vi } from "vitest";
|
|
import { EmexService } from "./emex.service";
|
|
|
|
// ConfigService.get(key, default) returns the raw ENV STRING (NestJS does not
|
|
// coerce <number> generics at runtime). These tests guard the regression where a
|
|
// string port range made the proxy-port arithmetic do string concat
|
|
// (45 + "10001" = "4510001"), producing an out-of-range port that crashed the
|
|
// whole app with undici "Invalid URL" at construction time.
|
|
function makeConfig(overrides: Record<string, string>): ConfigService {
|
|
return {
|
|
get: vi.fn((key: string, def?: unknown) =>
|
|
Object.hasOwn(overrides, key) ? overrides[key] : def,
|
|
),
|
|
} as unknown as ConfigService;
|
|
}
|
|
|
|
const browser = {} as never;
|
|
const redis = { set: vi.fn() } as never;
|
|
const posthog = {} as never;
|
|
const proxyTelemetry = { record: vi.fn() } as never;
|
|
const proxyHealth = {
|
|
isFloxyDown: vi.fn(() => false),
|
|
reportFloxyFailure: vi.fn(),
|
|
reportFloxySuccess: vi.fn(),
|
|
} as never;
|
|
|
|
describe("EmexService proxy-port coercion (regression)", () => {
|
|
it("does not throw 'Invalid URL' when ports arrive as strings over a real range", () => {
|
|
const config = makeConfig({
|
|
EMEX_USE_PROXY: "true",
|
|
EMEX_PROXY_HOST: "74.81.81.81",
|
|
EMEX_PROXY_PORT_START: "10001",
|
|
EMEX_PROXY_PORT_END: "10099",
|
|
});
|
|
// Pre-fix: threw "Invalid URL" here (port "4510001" > 65535).
|
|
expect(
|
|
() => new EmexService(config, browser, redis, posthog, proxyTelemetry, proxyHealth),
|
|
).not.toThrow();
|
|
});
|
|
|
|
it("constructs with a single-port range (string env)", () => {
|
|
const config = makeConfig({
|
|
EMEX_USE_PROXY: "true",
|
|
EMEX_PROXY_PORT_START: "823",
|
|
EMEX_PROXY_PORT_END: "823",
|
|
});
|
|
expect(
|
|
() => new EmexService(config, browser, redis, posthog, proxyTelemetry, proxyHealth),
|
|
).not.toThrow();
|
|
});
|
|
|
|
it("falls back to a valid default when the port env is garbage", () => {
|
|
const config = makeConfig({
|
|
EMEX_USE_PROXY: "true",
|
|
EMEX_PROXY_PORT_START: "not-a-number",
|
|
EMEX_PROXY_PORT_END: "999999",
|
|
});
|
|
expect(
|
|
() => new EmexService(config, browser, redis, posthog, proxyTelemetry, proxyHealth),
|
|
).not.toThrow();
|
|
});
|
|
|
|
it("constructs cleanly with the proxy disabled", () => {
|
|
const config = makeConfig({ EMEX_USE_PROXY: "false" });
|
|
expect(
|
|
() => new EmexService(config, browser, redis, posthog, proxyTelemetry, proxyHealth),
|
|
).not.toThrow();
|
|
});
|
|
});
|