mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:00:42 +00:00
refactor(slack): reuse default write clients
This commit is contained in:
@@ -12,6 +12,7 @@ vi.mock("./monitor/media.js", () => ({
|
||||
vi.mock("./client.js", () => ({
|
||||
createSlackWebClient: createSlackWebClientMock,
|
||||
createSlackWriteClient: createSlackWebClientMock,
|
||||
getSlackWriteClient: createSlackWebClientMock,
|
||||
}));
|
||||
|
||||
let downloadSlackFile: typeof import("./actions.js").downloadSlackFile;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { resolveSlackAccount } from "./accounts.js";
|
||||
import { buildSlackBlocksFallbackText } from "./blocks-fallback.js";
|
||||
import { validateSlackBlocksArray } from "./blocks-input.js";
|
||||
import { createSlackWebClient, createSlackWriteClient } from "./client.js";
|
||||
import { createSlackWebClient, getSlackWriteClient } from "./client.js";
|
||||
import { resolveSlackMedia } from "./monitor/media.js";
|
||||
import type { SlackMediaResult } from "./monitor/media.js";
|
||||
import { sendMessageSlack } from "./send.js";
|
||||
@@ -81,7 +81,7 @@ async function getClient(opts: SlackActionClientOpts = {}, mode: "read" | "write
|
||||
return opts.client;
|
||||
}
|
||||
const token = resolveToken(opts.token, opts.accountId, opts.cfg);
|
||||
return mode === "write" ? createSlackWriteClient(token) : createSlackWebClient(token);
|
||||
return mode === "write" ? getSlackWriteClient(token) : createSlackWebClient(token);
|
||||
}
|
||||
|
||||
async function resolveBotUserId(client: WebClient) {
|
||||
|
||||
@@ -14,6 +14,8 @@ vi.mock("@slack/web-api", () => {
|
||||
|
||||
let createSlackWebClient: typeof import("./client.js").createSlackWebClient;
|
||||
let createSlackWriteClient: typeof import("./client.js").createSlackWriteClient;
|
||||
let getSlackWriteClient: typeof import("./client.js").getSlackWriteClient;
|
||||
let clearSlackWriteClientCacheForTest: typeof import("./client.js").clearSlackWriteClientCacheForTest;
|
||||
let resolveSlackWebClientOptions: typeof import("./client.js").resolveSlackWebClientOptions;
|
||||
let resolveSlackWriteClientOptions: typeof import("./client.js").resolveSlackWriteClientOptions;
|
||||
let SLACK_DEFAULT_RETRY_OPTIONS: typeof import("./client.js").SLACK_DEFAULT_RETRY_OPTIONS;
|
||||
@@ -25,6 +27,8 @@ beforeAll(async () => {
|
||||
({
|
||||
createSlackWebClient,
|
||||
createSlackWriteClient,
|
||||
getSlackWriteClient,
|
||||
clearSlackWriteClientCacheForTest,
|
||||
resolveSlackWebClientOptions,
|
||||
resolveSlackWriteClientOptions,
|
||||
SLACK_DEFAULT_RETRY_OPTIONS,
|
||||
@@ -35,6 +39,7 @@ beforeAll(async () => {
|
||||
|
||||
beforeEach(() => {
|
||||
WebClient.mockClear();
|
||||
clearSlackWriteClientCacheForTest();
|
||||
});
|
||||
|
||||
describe("slack web client config", () => {
|
||||
@@ -93,6 +98,29 @@ describe("slack web client config", () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("reuses default write clients per token", () => {
|
||||
const first = getSlackWriteClient("xoxb-test");
|
||||
const second = getSlackWriteClient("xoxb-test");
|
||||
|
||||
expect(second).toBe(first);
|
||||
expect(WebClient).toHaveBeenCalledTimes(1);
|
||||
expect(WebClient).toHaveBeenCalledWith(
|
||||
"xoxb-test",
|
||||
expect.objectContaining({
|
||||
maxRequestConcurrency: 1,
|
||||
retryConfig: SLACK_WRITE_RETRY_OPTIONS,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps default write clients separated by token", () => {
|
||||
const first = getSlackWriteClient("xoxb-one");
|
||||
const second = getSlackWriteClient("xoxb-two");
|
||||
|
||||
expect(second).not.toBe(first);
|
||||
expect(WebClient).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("slack proxy agent", () => {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { type WebClientOptions, WebClient } from "@slack/web-api";
|
||||
import { resolveSlackWebClientOptions, resolveSlackWriteClientOptions } from "./client-options.js";
|
||||
|
||||
const SLACK_WRITE_CLIENT_CACHE_MAX = 32;
|
||||
const slackWriteClientCache = new Map<string, WebClient>();
|
||||
|
||||
export {
|
||||
resolveSlackWebClientOptions,
|
||||
resolveSlackWriteClientOptions,
|
||||
@@ -14,3 +18,25 @@ export function createSlackWebClient(token: string, options: WebClientOptions =
|
||||
export function createSlackWriteClient(token: string, options: WebClientOptions = {}) {
|
||||
return new WebClient(token, resolveSlackWriteClientOptions(options));
|
||||
}
|
||||
|
||||
export function getSlackWriteClient(token: string): WebClient {
|
||||
const cached = slackWriteClientCache.get(token);
|
||||
if (cached) {
|
||||
slackWriteClientCache.delete(token);
|
||||
slackWriteClientCache.set(token, cached);
|
||||
return cached;
|
||||
}
|
||||
const client = createSlackWriteClient(token);
|
||||
if (slackWriteClientCache.size >= SLACK_WRITE_CLIENT_CACHE_MAX) {
|
||||
const oldestToken = slackWriteClientCache.keys().next().value;
|
||||
if (oldestToken) {
|
||||
slackWriteClientCache.delete(oldestToken);
|
||||
}
|
||||
}
|
||||
slackWriteClientCache.set(token, client);
|
||||
return client;
|
||||
}
|
||||
|
||||
export function clearSlackWriteClientCacheForTest(): void {
|
||||
slackWriteClientCache.clear();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import type { SlackTokenSource } from "./accounts.js";
|
||||
import { resolveSlackAccount } from "./accounts.js";
|
||||
import { buildSlackBlocksFallbackText } from "./blocks-fallback.js";
|
||||
import { validateSlackBlocksArray } from "./blocks-input.js";
|
||||
import { createSlackWriteClient } from "./client.js";
|
||||
import { getSlackWriteClient } from "./client.js";
|
||||
import { markdownToSlackMrkdwnChunks } from "./format.js";
|
||||
import { SLACK_TEXT_LIMIT } from "./limits.js";
|
||||
import { loadOutboundMediaFromUrl } from "./runtime-api.js";
|
||||
@@ -397,7 +397,7 @@ async function sendMessageSlackQueued(params: {
|
||||
blocks?: (Block | KnownBlock)[];
|
||||
}): Promise<SlackSendResult> {
|
||||
const { opts, cfg, account, token, recipient, blocks, trimmedMessage } = params;
|
||||
const client = opts.client ?? createSlackWriteClient(token);
|
||||
const client = opts.client ?? getSlackWriteClient(token);
|
||||
const { channelId } = await resolveChannelId(client, recipient, {
|
||||
accountId: account.accountId,
|
||||
token,
|
||||
|
||||
Reference in New Issue
Block a user