fix: raise and configure per-user gateway session capacity
This commit is contained in:
@@ -70,6 +70,24 @@ test("loadConfig rejects the removed local DWS architecture", () => {
|
||||
}), /禁止配置本地 DWS/);
|
||||
});
|
||||
|
||||
test("gateway session capacity defaults to 32 and validates operator overrides", () => {
|
||||
const env = {
|
||||
APP_MODE: "gateway", DINGTALK_CLIENT_ID: "mock-key", DINGTALK_CLIENT_SECRET: "mock-secret",
|
||||
DINGTALK_CORP_ID: "mock-corp", MCP_PUBLIC_BASE_URL: "https://approval.example.test",
|
||||
MCP_REMOTE_AUTH_ENABLED: "true", MCP_SESSION_SECRET: "mock-session-secret-with-at-least-32-bytes",
|
||||
MCP_APPROVAL_REF_SECRET: "mock-reference-secret-with-at-least-32-bytes",
|
||||
XFT_OPEN_API_ENABLED: "true", XFT_OPEN_API_APP_ID: "mock-app",
|
||||
XFT_OPEN_API_AUTHORITY_SECRET: "1".repeat(64), XFT_OPEN_API_ENTERPRISE_ID: "mock-enterprise",
|
||||
};
|
||||
assert.equal(loadConfig(env).mcpSessionMaxPerUser, 32);
|
||||
for (const value of ["1", "64", "1000"]) {
|
||||
assert.equal(loadConfig({ ...env, MCP_SESSION_MAX_PER_USER: value }).mcpSessionMaxPerUser, Number(value));
|
||||
}
|
||||
for (const value of ["0", "-1", "1.5", "invalid", "1001"]) {
|
||||
assert.throws(() => loadConfig({ ...env, MCP_SESSION_MAX_PER_USER: value }), /MCP_SESSION_MAX_PER_USER/);
|
||||
}
|
||||
});
|
||||
|
||||
test("loadConfig reads AuthoritySecret from the second line of an XFT portal credential file", () => {
|
||||
const directory = mkdtempSync(join(tmpdir(), "ding-mcp-xft-openapi-config-"));
|
||||
const secretPath = join(directory, "xft.key");
|
||||
|
||||
+19
-1
@@ -25,7 +25,8 @@ async function until(condition: () => boolean) {
|
||||
assert.fail("HTTP lifecycle event did not arrive");
|
||||
}
|
||||
|
||||
async function harness(t: TestContext, readTodos: () => Promise<void> = async () => {}) {
|
||||
async function harness(t: TestContext, readTodos: () => Promise<void> = async () => {},
|
||||
limits: { maxSessionsPerUser?: number } = { maxSessionsPerUser: 8 }) {
|
||||
let time = Date.now();
|
||||
let closedStreams = 0;
|
||||
const app = express();
|
||||
@@ -36,6 +37,7 @@ async function harness(t: TestContext, readTodos: () => Promise<void> = async ()
|
||||
});
|
||||
const routes = installMcpTransports(app, {
|
||||
now: () => time,
|
||||
maxSessionsPerUser: limits.maxSessionsPerUser,
|
||||
authenticate: (req, res, next) => {
|
||||
// Synthetic bearer credentials; no external approval or OAuth writes.
|
||||
const token = req.get("authorization");
|
||||
@@ -118,6 +120,22 @@ test("old bridge disconnects release eight occupied slots without a client upgra
|
||||
assert.equal((await h.rpc(sessions[0]!.transport.sessionId, "a", "tools/list")).response.status, 404);
|
||||
});
|
||||
|
||||
test("default gateway capacity admits 32 live connections for one user", async (t) => {
|
||||
const h = await harness(t, undefined, {});
|
||||
const sessions = [];
|
||||
for (let i = 0; i < 32; i += 1) sessions.push(await h.connect());
|
||||
assert.equal((await h.rpc()).response.status, 429);
|
||||
assert.ok((await sessions[0]!.client.listTools()).tools.length > 0);
|
||||
assert.ok((await sessions[31]!.client.listTools()).tools.length > 0);
|
||||
});
|
||||
|
||||
test("operator override permits 64 sessions while retaining its configured cap", async (t) => {
|
||||
const h = await harness(t, undefined, { maxSessionsPerUser: 64 });
|
||||
const results = await Promise.all(Array.from({ length: 65 }, () => h.rpc()));
|
||||
assert.equal(results.filter(({ response }) => response.status === 200).length, 64);
|
||||
assert.equal(results.filter(({ response }) => response.status === 429).length, 1);
|
||||
});
|
||||
|
||||
test("live streams survive idle cleanup and capacity does not evict another user", async (t) => {
|
||||
const h = await harness(t);
|
||||
const sessions = [];
|
||||
|
||||
Reference in New Issue
Block a user