session-guard-warmup-intercept.test.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. import { beforeEach, describe, expect, test, vi } from "vitest";
  2. import type { ProxySession } from "@/app/v1/_lib/proxy/session";
  3. const getCachedSystemSettingsMock = vi.fn();
  4. const extractClientSessionIdMock = vi.fn();
  5. const getOrCreateSessionIdMock = vi.fn();
  6. const getNextRequestSequenceMock = vi.fn();
  7. const storeSessionRequestBodyMock = vi.fn(async () => undefined);
  8. const storeSessionClientRequestMetaMock = vi.fn(async () => undefined);
  9. const storeSessionMessagesMock = vi.fn(async () => undefined);
  10. const storeSessionInfoMock = vi.fn(async () => undefined);
  11. const generateSessionIdMock = vi.fn();
  12. const trackSessionMock = vi.fn(async () => undefined);
  13. vi.mock("@/lib/config", () => ({
  14. getCachedSystemSettings: () => getCachedSystemSettingsMock(),
  15. }));
  16. vi.mock("@/lib/session-manager", () => ({
  17. SessionManager: {
  18. extractClientSessionId: extractClientSessionIdMock,
  19. getOrCreateSessionId: getOrCreateSessionIdMock,
  20. getNextRequestSequence: getNextRequestSequenceMock,
  21. storeSessionRequestBody: storeSessionRequestBodyMock,
  22. storeSessionClientRequestMeta: storeSessionClientRequestMetaMock,
  23. storeSessionMessages: storeSessionMessagesMock,
  24. storeSessionInfo: storeSessionInfoMock,
  25. generateSessionId: generateSessionIdMock,
  26. },
  27. }));
  28. vi.mock("@/lib/session-tracker", () => ({
  29. SessionTracker: {
  30. trackSession: trackSessionMock,
  31. },
  32. }));
  33. vi.mock("@/lib/logger", () => ({
  34. logger: {
  35. debug: vi.fn(),
  36. info: vi.fn(),
  37. warn: vi.fn(),
  38. error: vi.fn(),
  39. fatal: vi.fn(),
  40. trace: vi.fn(),
  41. },
  42. }));
  43. async function loadGuard() {
  44. const mod = await import("@/app/v1/_lib/proxy/session-guard");
  45. return mod.ProxySessionGuard;
  46. }
  47. function createMockSession(overrides: Partial<ProxySession> = {}): ProxySession {
  48. const session: any = {
  49. authState: {
  50. success: true,
  51. user: { id: 1, name: "u" },
  52. key: { id: 1, name: "k" },
  53. apiKey: "api-key",
  54. },
  55. request: {
  56. message: {},
  57. model: "claude-sonnet-4-5-20250929",
  58. },
  59. headers: new Headers(),
  60. userAgent: "claude_cli/1.0",
  61. requestUrl: "http://localhost/v1/messages",
  62. method: "POST",
  63. originalFormat: "claude",
  64. sessionId: null,
  65. setSessionId(id: string) {
  66. this.sessionId = id;
  67. },
  68. setRequestSequence(seq: number) {
  69. this.requestSequence = seq;
  70. },
  71. getRequestSequence() {
  72. return this.requestSequence ?? 1;
  73. },
  74. generateDeterministicSessionId() {
  75. return "deterministic_session_id";
  76. },
  77. getMessages() {
  78. return [];
  79. },
  80. getMessagesLength() {
  81. return 1;
  82. },
  83. isWarmupRequest() {
  84. return true;
  85. },
  86. } satisfies Partial<ProxySession>;
  87. return { ...session, ...overrides } as ProxySession;
  88. }
  89. beforeEach(() => {
  90. vi.clearAllMocks();
  91. extractClientSessionIdMock.mockReturnValue(null);
  92. getOrCreateSessionIdMock.mockResolvedValue("session_assigned");
  93. getNextRequestSequenceMock.mockResolvedValue(1);
  94. getCachedSystemSettingsMock.mockResolvedValue({ interceptAnthropicWarmupRequests: true });
  95. });
  96. describe("ProxySessionGuard:warmup 拦截不应计入并发会话", () => {
  97. test("当 warmup 且开关开启时,不应调用 SessionTracker.trackSession", async () => {
  98. const ProxySessionGuard = await loadGuard();
  99. const session = createMockSession({ isWarmupRequest: () => true });
  100. await ProxySessionGuard.ensure(session);
  101. expect(trackSessionMock).not.toHaveBeenCalled();
  102. expect(session.sessionId).toBe("session_assigned");
  103. });
  104. test("当 warmup 但开关关闭时,应正常调用 SessionTracker.trackSession", async () => {
  105. const ProxySessionGuard = await loadGuard();
  106. getCachedSystemSettingsMock.mockResolvedValueOnce({ interceptAnthropicWarmupRequests: false });
  107. const session = createMockSession({ isWarmupRequest: () => true });
  108. await ProxySessionGuard.ensure(session);
  109. expect(trackSessionMock).toHaveBeenCalledTimes(1);
  110. expect(trackSessionMock).toHaveBeenCalledWith("session_assigned", 1, 1);
  111. });
  112. });