Skip to content

Commit 482a6d2

Browse files
committed
Paginate through users
If there are/have been over 1000 users in an organization, the eligible_user_ids method in loads_slack_channel_members would only retrieve the first 1000. This change adds a method to follow any pagination cursors and combine user pages together to ensure we have a complete user list to compare to when intersecting with the channel member list. This change also adds a limit of 200 for user retrievable, as recommended by Slack's API guide.
1 parent f7c3a93 commit 482a6d2

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

app/services/slack/loads_slack_channel_members.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,21 @@ def call(channel:)
1414

1515
def eligible_user_ids
1616
response = retry_when_rate_limited do
17-
ClientWrapper.client.users_list
17+
ClientWrapper.client.users_list(limit: 200)
1818
end
1919

20-
(response&.members || []).reject { |u| u.is_bot }.map(&:id)
20+
members = get_paged_members(cursor: response&.response_metadata&.next_cursor, members: response&.members || [])
21+
(members || []).reject { |u| u.is_bot }.map(&:id)
22+
end
23+
24+
def get_paged_members(cursor:, members:)
25+
while cursor.present?
26+
response = ClientWrapper.client.users_list(cursor: cursor, limit: 200)
27+
members.append(response.members)
28+
cursor = response.response_metadata&.next_cursor
29+
end
30+
31+
members.flatten
2132
end
2233
end
2334
end

spec/lib/slack/loads_slack_channel_members_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,33 @@
3535
expect(members).to eq(slack_members)
3636
end
3737

38+
it "loads members found in a channel when pagination is required" do
39+
all_slack_users = (0..205).map do |id|
40+
Slack::Messages::Message.new(id: "USER_ID_#{id}")
41+
end
42+
43+
slack_members = [
44+
"USER_ID_1",
45+
"USER_ID_3",
46+
"USER_ID_205"
47+
]
48+
49+
response_metadata = Slack::Messages::Message.new(next_cursor: "cursor")
50+
expect(@slack_client).to receive(:users_list).with(limit: 200) {
51+
Slack::Messages::Message.new(ok: true, members: all_slack_users[0..199], response_metadata: response_metadata)
52+
}
53+
expect(@slack_client).to receive(:users_list).with(cursor: response_metadata.next_cursor, limit: 200) {
54+
Slack::Messages::Message.new(ok: true, members: all_slack_users[200..])
55+
}
56+
expect(@slack_client).to receive(:conversations_members).with(channel: "CHANNEL_ID", limit: 1000) {
57+
Slack::Messages::Message.new(ok: true, members: slack_members)
58+
}
59+
60+
members = subject.call(channel: "CHANNEL_ID")
61+
62+
expect(members).to eq(slack_members)
63+
end
64+
3865
it "excludes bots from the returned users" do
3966
slack_user = Slack::Messages::Message.new(id: "USER_ID", is_bot: false)
4067
slack_app = Slack::Messages::Message.new(id: "APP_ID", is_bot: true)

0 commit comments

Comments
 (0)