aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrygve Aaberge <trygveaa@gmail.com>2024-03-28 23:43:50 +0100
committerTrygve Aaberge <trygveaa@gmail.com>2024-03-29 00:00:15 +0100
commit0b5069e600b6fbe72affed97f0b36ef923ba4072 (patch)
treef47eba1ab153648e6e24749bc89fb8dfb27286bb
parentec503d0935cbc171fbe7762a83c36a0e1160efa7 (diff)
downloadwee-slack-0b5069e600b6fbe72affed97f0b36ef923ba4072.tar.gz
Retry fetching users with fewer users on errors
Apparently it varies how many users can be fetched in one request with the users.info method. I have had successful requests with 4096 users, while some people have reported getting HTTP 500 when fetching 1000 users and one person got an error response with error `too_many_users` when fetching 500 users. So when we get either of those errors, reduce the number of users we fetch in one request and try again until it works or the number of users has been reduced to 1. Fixes #924
-rw-r--r--slack/slack_api.py38
-rw-r--r--slack/slack_workspace.py1
2 files changed, 34 insertions, 5 deletions
diff --git a/slack/slack_api.py b/slack/slack_api.py
index d3e52e4..b0ef14d 100644
--- a/slack/slack_api.py
+++ b/slack/slack_api.py
@@ -12,7 +12,7 @@ from typing import (
)
from urllib.parse import urlencode
-from slack.error import SlackApiError
+from slack.error import HttpError, SlackApiError
from slack.http import http_request
from slack.shared import shared
from slack.slack_message import SlackTs
@@ -38,8 +38,10 @@ if TYPE_CHECKING:
from slack_api.slack_usergroups_info import SlackUsergroupsInfoResponse
from slack_api.slack_users_conversations import SlackUsersConversationsResponse
from slack_api.slack_users_info import (
+ SlackUserInfo,
SlackUserInfoResponse,
SlackUsersInfoResponse,
+ SlackUsersInfoSuccessResponse,
)
from slack_api.slack_users_prefs import SlackUsersPrefsGetResponse
from slack_edgeapi.slack_usergroups_info import SlackEdgeUsergroupsInfoResponse
@@ -277,14 +279,40 @@ class SlackApi(SlackApiCommon):
raise SlackApiError(self.workspace, method, response, params)
return response
- async def fetch_users_info(self, user_ids: Iterable[str]):
+ async def fetch_users_info(
+ self, user_ids: Iterable[str]
+ ) -> SlackUsersInfoSuccessResponse[SlackUserInfo]:
responses = await gather(
*(
self._fetch_users_info_without_splitting(user_ids_batch)
- for user_ids_batch in chunked(user_ids, 500)
- )
+ for user_ids_batch in chunked(
+ user_ids, self.workspace.max_users_per_fetch_request
+ )
+ ),
+ return_exceptions=True,
)
- users = list(chain(*(response["users"] for response in responses)))
+
+ errors = [r for r in responses if isinstance(r, BaseException)]
+ if errors:
+ if (
+ any(
+ # The users.info method may respond with 500 if we request too many users in one request
+ (isinstance(e, HttpError) and e.http_status_code == 500)
+ or (
+ isinstance(e, SlackApiError)
+ and e.response["error"] == "too_many_users"
+ )
+ for e in errors
+ )
+ and self.workspace.max_users_per_fetch_request > 1
+ ):
+ self.workspace.max_users_per_fetch_request //= 2
+ return await self.fetch_users_info(user_ids)
+ else:
+ raise errors[0]
+
+ success_responses = [r for r in responses if not isinstance(r, BaseException)]
+ users = list(chain(*(response["users"] for response in success_responses)))
response: SlackUsersInfoResponse = {"ok": True, "users": users}
return response
diff --git a/slack/slack_workspace.py b/slack/slack_workspace.py
index 99bd8aa..a1289a0 100644
--- a/slack/slack_workspace.py
+++ b/slack/slack_workspace.py
@@ -219,6 +219,7 @@ class SlackWorkspace:
self.usergroups = SlackUsergroups(self)
self.muted_channels: Set[str] = set()
self.custom_emojis: Dict[str, str] = {}
+ self.max_users_per_fetch_request = 512
def __repr__(self):
return f"{self.__class__.__name__}({self.name})"