























@@ -574,9 +574,11 @@ describe("resolveGatewayReloadSettings", () => {
574574type WatcherHandler = () => void;
575575type WatcherEvent = "add" | "change" | "unlink" | "error";
576576577-function createWatcherMock() {
577+function createWatcherMock(effectiveUsePolling?: boolean) {
578578const handlers = new Map<WatcherEvent, WatcherHandler[]>();
579579return {
580+ effectiveUsePolling,
581+options: { usePolling: false },
580582on(event: WatcherEvent, handler: WatcherHandler) {
581583const existing = handlers.get(event) ?? [];
582584existing.push(handler);
@@ -1602,9 +1604,15 @@ describe("startGatewayConfigReloader watcher error recovery", () => {
1602160416031605function startReloaderWithWatchers(watchers: ReturnType<typeof createWatcherMock>[]) {
16041606const watchSpy = vi.spyOn(chokidar, "watch");
1605-for (const watcher of watchers) {
1606-watchSpy.mockReturnValueOnce(watcher as unknown as never);
1607-}
1607+let watcherIndex = 0;
1608+watchSpy.mockImplementation((_path, options) => {
1609+const watcher = watchers[watcherIndex++];
1610+if (!watcher) {
1611+throw new Error("missing watcher mock");
1612+}
1613+watcher.options.usePolling = watcher.effectiveUsePolling ?? Boolean(options?.usePolling);
1614+return watcher as unknown as never;
1615+});
16081616const log = { info: vi.fn(), warn: vi.fn(), error: vi.fn() };
16091617const reloader = startGatewayConfigReloader({
16101618initialConfig: { gateway: { reload: { debounceMs: 0 } } },
@@ -1676,9 +1684,7 @@ describe("startGatewayConfigReloader watcher error recovery", () => {
16761684// Fourth native error triggers degradation to polling mode (not disabled).
16771685watchers[3]?.emit("error");
16781686expect(reloader.hotReloadStatus()).toBe("active");
1679-expect(log.warn).toHaveBeenCalledWith(
1680-expect.stringContaining("degrading to polling mode"),
1681-);
1687+expect(log.warn).toHaveBeenCalledWith(expect.stringContaining("degrading to polling mode"));
16821688await vi.advanceTimersByTimeAsync(500);
16831689expect(watchSpy).toHaveBeenCalledTimes(5);
16841690expect(watchOptions(4)?.usePolling).toBe(true);
@@ -1772,6 +1778,45 @@ describe("startGatewayConfigReloader watcher error recovery", () => {
17721778}
17731779});
177417801781+it("uses chokidar's effective polling mode when the platform forces it on", async () => {
1782+const originalVitest = process.env.VITEST;
1783+const originalChokidarPolling = process.env.CHOKIDAR_USEPOLLING;
1784+delete process.env.VITEST;
1785+delete process.env.CHOKIDAR_USEPOLLING;
1786+let reloader: { stop: () => Promise<void>; hotReloadStatus: () => string } | undefined;
1787+try {
1788+const watchers = Array.from({ length: 4 }, () => createWatcherMock(true));
1789+const started = startReloaderWithWatchers(watchers);
1790+const { log } = started;
1791+reloader = started.reloader;
1792+const backoffs = [500, 2000, 5000] as const;
1793+1794+for (let index = 0; index < watchers.length - 1; index += 1) {
1795+watchers[index]?.emit("error");
1796+await vi.advanceTimersByTimeAsync(backoffs[index] ?? 0);
1797+}
1798+watchers.at(-1)?.emit("error");
1799+1800+expect(reloader.hotReloadStatus()).toBe("disabled");
1801+expect(log.warn).not.toHaveBeenCalledWith(
1802+expect.stringContaining("degrading to polling mode"),
1803+);
1804+expect(log.error).toHaveBeenCalledWith(expect.stringContaining("in polling mode"));
1805+} finally {
1806+if (originalVitest === undefined) {
1807+delete process.env.VITEST;
1808+} else {
1809+process.env.VITEST = originalVitest;
1810+}
1811+if (originalChokidarPolling === undefined) {
1812+delete process.env.CHOKIDAR_USEPOLLING;
1813+} else {
1814+process.env.CHOKIDAR_USEPOLLING = originalChokidarPolling;
1815+}
1816+await reloader?.stop();
1817+}
1818+});
1819+17751820it("does not report polling fallback when chokidar polling is forced off", async () => {
17761821const originalVitest = process.env.VITEST;
17771822const originalChokidarPolling = process.env.CHOKIDAR_USEPOLLING;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。