




















@@ -3,8 +3,10 @@ import {
33__testing as controlPlaneRateLimitTesting,
44resolveControlPlaneRateLimitKey,
55} from "./control-plane-rate-limit.js";
6+import { isRetryableGatewayStartupUnavailableError } from "./protocol/startup-unavailable.js";
67import { handleGatewayRequest } from "./server-methods.js";
78import type { GatewayRequestHandler } from "./server-methods/types.js";
9+import { STARTUP_UNAVAILABLE_GATEWAY_METHODS } from "./server-startup-unavailable-methods.js";
810911const noWebchat = () => false;
1012@@ -131,32 +133,37 @@ describe("gateway control-plane write rate limit", () => {
131133expect(handlerCalls).toHaveBeenCalledTimes(4);
132134});
133135134-it("blocks startup-gated methods before dispatch", async () => {
135-const handlerCalls = vi.fn();
136-const handler: GatewayRequestHandler = (opts) => {
137-handlerCalls(opts);
138-opts.respond(true, undefined, undefined);
139-};
140-const context = {
141- ...buildContext(),
142-unavailableGatewayMethods: new Set(["chat.history", "models.list"]),
143-} as Parameters<typeof handleGatewayRequest>[0]["context"];
144-const client = buildClient();
145-146-const blocked = await runRequest({ method: "models.list", context, client, handler });
147-148-expect(handlerCalls).not.toHaveBeenCalled();
149-expect(blocked).toHaveBeenCalledWith(
150-false,
151-undefined,
152-expect.objectContaining({
153-code: "UNAVAILABLE",
154-retryable: true,
155-retryAfterMs: 500,
156-details: { method: "models.list" },
157-}),
158-);
159-});
136+it.each(STARTUP_UNAVAILABLE_GATEWAY_METHODS)(
137+"blocks startup-gated method %s before dispatch with a retryable startup error",
138+async (method) => {
139+const handlerCalls = vi.fn();
140+const handler: GatewayRequestHandler = (opts) => {
141+handlerCalls(opts);
142+opts.respond(true, undefined, undefined);
143+};
144+const context = {
145+ ...buildContext(),
146+unavailableGatewayMethods: new Set(STARTUP_UNAVAILABLE_GATEWAY_METHODS),
147+} as Parameters<typeof handleGatewayRequest>[0]["context"];
148+const client = buildClient();
149+150+const blocked = await runRequest({ method, context, client, handler });
151+152+expect(handlerCalls).not.toHaveBeenCalled();
153+expect(blocked).toHaveBeenCalledWith(
154+false,
155+undefined,
156+expect.objectContaining({
157+code: "UNAVAILABLE",
158+retryable: true,
159+retryAfterMs: 500,
160+details: { reason: "startup-sidecars", method },
161+}),
162+);
163+const error = blocked.mock.calls[0]?.[2];
164+expect(isRetryableGatewayStartupUnavailableError(error)).toBe(true);
165+},
166+);
160167161168it("uses connId fallback when both device and client IP are unknown", () => {
162169const key = resolveControlPlaneRateLimitKey({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。