@@ -100,28 +100,47 @@ async function getSlackChannelsForToken(integration: AuthenticatableIntegration)
100100
101101type Channels = Awaited<ReturnType<WebClient["conversations"]["list"]>>["channels"];
102102
103- async function getSlackConversationsPage(client: WebClient, nextCursor?: string) {
104- return client.conversations.list({
105- types: "public_channel,private_channel",
106- exclude_archived: true,
107- cursor: nextCursor,
108- });
109- }
110-
111103async function getAllSlackConversations(client: WebClient) {
112104 let nextCursor: string | undefined = undefined;
113105 let channels: Channels = [];
114106
115- do {
116- const response = await getSlackConversationsPage(client, nextCursor);
117-
118- if (!response.ok) {
119- throw new Error(`Failed to get channels: ${response.error}`);
107+ try {
108+ do {
109+ // The `tryCatch` util runs into a type error due to self referencing.
110+ // So we fall back to a good old try/catch block here.
111+ const response = await client.conversations.list({
112+ types: "public_channel,private_channel",
113+ exclude_archived: true,
114+ cursor: nextCursor,
115+ limit: 999,
116+ });
117+
118+ channels = channels.concat(response.channels ?? []);
119+ nextCursor = response.response_metadata?.next_cursor;
120+ } while (nextCursor);
121+ } catch (error) {
122+ if (error && isSlackError(error) && error.data.error === "ratelimited") {
123+ logger.warn("Rate limiting issue occurred while fetching Slack channels", {
124+ error,
125+ });
126+
127+ // This is a workaround to the current way we handle Slack channels for creating alerts.
128+ // For workspaces with a lot of channels (>10000) we might hit the rate limit for this slack endpoint,
129+ // as multiple requests are needed to fetch all channels.
130+ // We use the largest allowed page size of 999 to reduce the chance of hitting the rate limit.
131+
132+ // This is mainly due to workspaces with a large number of archived channels,
133+ // which this slack endpoint unfortunately filters out only after fetching the page of channels without applying any filters first.
134+ // https://api.slack.com/methods/conversations.list#markdown
135+
136+ // We expect most workspaces not to run into this issue, but if they do, we at least return some channels.
137+ // In the future, we might revisit the way we handle Slack channels and cache them on our side to support
138+ // proper searching. Until then, we track occurrences of this issue using a metric.
139+ return channels;
120140 }
121141
122- channels = channels.concat(response.channels ?? []);
123- nextCursor = response.response_metadata?.next_cursor;
124- } while (nextCursor);
142+ throw error;
143+ }
125144
126145 return channels;
127146}
0 commit comments