Bugfix/slack bot channel config (#4585)

* friendlier handling of slack channel retrieval

* retry on downgrade_postgres deadlock

* fix comment

* text

---------

Co-authored-by: Richard Kuo (Onyx) <rkuo@onyx.app>
This commit is contained in:
rkuo-danswer
2025-04-23 13:00:03 -07:00
committed by GitHub
parent 07f04e35ec
commit c9a609b7d8
3 changed files with 37 additions and 19 deletions

View File

@ -36,6 +36,8 @@ from onyx.utils.logger import setup_logger
from onyx.utils.telemetry import create_milestone_and_report from onyx.utils.telemetry import create_milestone_and_report
from shared_configs.contextvars import get_current_tenant_id from shared_configs.contextvars import get_current_tenant_id
SLACK_API_CHANNELS_PER_PAGE = 100
SLACK_MAX_RETURNED_CHANNELS = 500
logger = setup_logger() logger = setup_logger()
@ -355,10 +357,6 @@ def list_bot_configs(
] ]
MAX_SLACK_PAGES = 5
SLACK_API_CHANNELS_PER_PAGE = 100
@router.get( @router.get(
"/admin/slack-app/bots/{bot_id}/channels", "/admin/slack-app/bots/{bot_id}/channels",
) )
@ -368,6 +366,9 @@ def get_all_channels_from_slack_api(
_: User | None = Depends(current_admin_user), _: User | None = Depends(current_admin_user),
) -> list[SlackChannel]: ) -> list[SlackChannel]:
""" """
Returns a list of available slack channels for the slack bot, limited to
SLACK_MAX_RETURNED_CHANNELS.
Fetches all channels in the Slack workspace using the conversations_list API. Fetches all channels in the Slack workspace using the conversations_list API.
This includes both public and private channels that are visible to the app, This includes both public and private channels that are visible to the app,
not just the ones the bot is a member of. not just the ones the bot is a member of.
@ -380,15 +381,12 @@ def get_all_channels_from_slack_api(
) )
client = WebClient(token=tokens["bot_token"], timeout=1) client = WebClient(token=tokens["bot_token"], timeout=1)
all_channels = [] all_channels: list[dict] = []
next_cursor = None next_cursor = None
current_page = 0
try: try:
# Use conversations_list to get all channels in the workspace (including ones the bot is not a member of) # Use conversations_list to get all channels in the workspace (including ones the bot is not a member of)
while current_page < MAX_SLACK_PAGES: while len(all_channels) < SLACK_MAX_RETURNED_CHANNELS:
current_page += 1
# Make API call with cursor if we have one # Make API call with cursor if we have one
if next_cursor: if next_cursor:
response = client.conversations_list( response = client.conversations_list(
@ -415,16 +413,13 @@ def get_all_channels_from_slack_api(
): ):
next_cursor = response["response_metadata"]["next_cursor"] next_cursor = response["response_metadata"]["next_cursor"]
if next_cursor: if next_cursor:
if current_page == MAX_SLACK_PAGES:
raise HTTPException(
status_code=400,
detail="Workspace has too many channels to paginate over in this call.",
)
continue continue
# If we get here, no more pages # If we get here, no more pages
break break
del all_channels[SLACK_MAX_RETURNED_CHANNELS:] # truncate the list
channels = [ channels = [
SlackChannel(id=channel["id"], name=channel["name"]) SlackChannel(id=channel["id"], name=channel["name"])
for channel in all_channels for channel in all_channels

View File

@ -273,6 +273,10 @@ def reset_postgres(
logger.warning( logger.warning(
f"Postgres downgrade timed out, retrying... ({_ + 1}/{NUM_TRIES})" f"Postgres downgrade timed out, retrying... ({_ + 1}/{NUM_TRIES})"
) )
except RuntimeError:
logger.warning(
f"Postgres downgrade exceptioned, retrying... ({_ + 1}/{NUM_TRIES})"
)
if not success: if not success:
raise RuntimeError("Postgres downgrade failed after 10 timeouts.") raise RuntimeError("Postgres downgrade failed after 10 timeouts.")

View File

@ -190,6 +190,25 @@ export function SlackChannelConfigFormFields({
} }
); );
// Define the helper text based on the state
const channelHelperText = useMemo(() => {
if (isLoading || error) {
// No helper text needed during loading or if there's an error
// (error message is shown separately)
return null;
}
if (!channelOptions || channelOptions.length === 0) {
return "No channels found. You can type any channel name in directly.";
}
let helpText = `Select a channel from the dropdown list or type any channel name in directly.`;
if (channelOptions.length >= 500) {
return `${helpText} (Retrieved the first ${channelOptions.length} channels.)`;
}
return helpText;
}, [isLoading, error, channelOptions]);
if (isLoading) { if (isLoading) {
return <ThreeDotsLoader />; return <ThreeDotsLoader />;
} }
@ -257,11 +276,11 @@ export function SlackChannelConfigFormFields({
/> />
)} )}
</Field> </Field>
{channelHelperText && (
<p className="mt-2 text-sm dark:text-neutral-400 text-neutral-600"> <p className="mt-2 text-sm dark:text-neutral-400 text-neutral-600">
Note: This list shows existing public and private channels (up {channelHelperText}
to 500). You can either select from the list or type any
channel name directly.
</p> </p>
)}
</> </>
)} )}
</> </>