0

I am working on a bot that streams post from the Steem Blockchain (using the synchronous beem library) and sends posts that fulfil certain criteria to a Discord channel (using the asynchronous Discord.py library). This is is my (simplified) code:

bot = commands.Bot(command_prefix="!")

async def send_discord(msg):
    await bot.wait_until_ready()
    await bot.send_message(bot.get_channel("mychannelid"), msg)

async def scan_post(post):
    """Scan queued Comment objects for defined patterns"""
    post.refresh()
    if post["author"] == "myusername":
        await loop.create_task(send_discord("New post found"))

async def start_blockchain():
    stream = map(blockchain.stream(opNames=["comment"]))
    for post in stream:
        await loop.create_task(scan_post(post))

if __name__ == '__main__':
    while True:
        loop.create_task(start_blockchain())
        try:
            loop.run_until_complete(bot.start(TOKEN))
        except Exception as error:
            bot.logout()
            logger.warning("Bot restarting "+repr(error))

Before I implemented discord.py I would just call the synchronous function scan_post(post) and it worked just fine, but now with the asynchronous implementation the posts are not processed fast enough and the stream has a rapidly increasing delay. If I make scan_post(post) a synchronous function, the processing time is fine, but the Discord websocket closes (or does not even open) and the bot goes offline. How can I solve this in a simple way (without rewriting the beem library)?

Julian
  • 99
  • 1
  • 1
  • 5
  • Is the `blockchain.stream()` call also blocking, or just the `post.refresh()`? Also, `map(blockchain.stream(...))` looks incorrect - `map` takes at least two arguments. – user4815162342 Sep 22 '18 at 05:33
  • For the blocking operations in your async code you can use `run_in_executor` (https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor) so, so they won't block the whole thread. There are also useful examples in documentation. – Vladimir Poghosyan Sep 27 '18 at 13:54

1 Answers1

1

I solved the problem: I run the beem stream in its own thread and the asynchronous functions in a second thread. With the janus library I can then add objects from the beam thread to a queue that is processed by the asynchronous thread.

Julian
  • 99
  • 1
  • 1
  • 5