Skip to content

AsyncIO loop is not being shared from RTMClient to WebClient #631

@juan-vg

Description

@juan-vg

Description

Describe your issue here.

What type of issue is this? (place an x in one of the [ ])

  • bug
  • enhancement (feature request)
  • question
  • documentation related
  • testing related
  • discussion

Requirements (place an x in each of the [ ])

  • I've read and understood the Contributing guidelines and have done my best effort to follow them.
  • I've read and agree to the Code of Conduct.
  • I've searched for any related issues and avoided creating a duplicate issue.

Bug Report

Filling out the following details about bugs will help us solve your issue sooner.

Reproducible in:

slackclient version: 2.5.0

python version: 3.7.6 (venv)

Steps to reproduce:

  1. Use SlackClient as part of a project, not only as a standalone stuff. The project uses other libraries that use asyncio
  2. Create a RTMClient, and set the loop as asyncio.get_event_loop() in order to use the same as the project
  3. When receiving a message, get the attached web_client and use it to send a message back

Expected result:

The message is sent

Actual result:

RuntimeError: this event loop is already running.

Explanation of what's going on and workaround:

What is actually happening is that the loop set to the RTMClient is not being shared with the attached WebClient.

The following code does the trick, but it's a workaround and not a real solution

import os
from slack import RTMClient
import asyncio
loop = asyncio.get_event_loop()

@RTMClient.run_on(event="message")
def say_hello(**payload):
  data = payload['data']
  web_client = payload['web_client']

#### WORKAROUND #########################
# Manually set the project's loop on the WebClient, even when it was set on the parent RTMClient
  web_client._event_loop = loop
  # Maybe you will also need the following line uncommented
  # web_client.run_async = True
##########################################

  if 'Hello' in data['text']:
    channel_id = data['channel']
    thread_ts = data['ts']
    user = data['user']

    web_client.chat_postMessage(
      channel=channel_id,
      text=f"Hi <@{user}>!",
      thread_ts=thread_ts
    )

slack_token = os.environ["SLACK_API_TOKEN"]
rtm_client = RTMClient(token=slack_token, loop=loop)
rtm_client.start()

Regarding uvloop:

If the main project's loop is not the common one but an uvloop, you will need to make some mods before getting the loop in order to set it on the RTMClient

...
import asyncio
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
...

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions