Allen Ye
Allen Ye

Reputation: 91

How to Prevent Overlapping Async Tasks When Using APScheduler with asyncio in Python?

I'm using APScheduler to schedule jobs that call various webhook functions asynchronously. However, I'm encountering an issue where overlapping tasks cause errors, particularly the Task got Future attached to a different loop error. This happens because APScheduler jobs might run at the same time, leading to multiple async tasks being scheduled on different event loops.

import asyncio
import logging
import traceback

channel_to_webhooks = {
    "channel_A": "webhook_url_A",
    "channel_B": "webhook_url_B",
    "channel_C": "webhook_url_C",
}

async def webhook_func_A(webhook_url, args):
    async with aiohttp.ClientSession() as session:
       await webhook.send(content=args.get("message))

async def webhook_func_B(webhook_url, args):
    pass

async def webhook_func_C(webhook_url, args):
    pass

def call_webhook(channel_name, args):
    channel_to_use = channel_to_webhooks.get(channel_name)
    try:
        if not channel_to_use:
            raise Exception(
                f"call_webhook: Could not find webhook channel for {channel_name}"
            )
        loop = asyncio.new_event_loop()
        if channel_name == "channel_A":
            loop.run_until_complete(webhook_func_A(channel_to_use, args))
        elif channel_name == "channel_B":
            loop.run_until_complete(webhook_func_B(channel_to_use, args))
        elif channel_name == "channel_C":
            loop.run_until_complete(webhook_func_C(channel_to_use, args))
        loop.close()
    except Exception as e:
        logging.error(
            f"Could not call webhook for channel {channel_name} and args {args} due to {e}, traceback is {traceback.format_exc()}"
        )

The error I receive is

Could not call webhook for channel some_channel and args {...} due to Task <Task pending name='Task-5651' coro=<webhook_cron_job() running at /app/backend/webhooks.py:173> cb=[run_until_complete.<locals>.done_cb()]>
got Future <Future pending> attached to a different loop, traceback is

Traceback (most recent call last):
  File "/app/backend/webhooks.py", line 197, in call_webhook
    loop.run_until_complete(webhook_cron_job(channel_to_use, args))
  File "uvloop/loop.pyx", line 1517, in uvloop.loop.Loop.run_until_complete
  File "/app/backend/webhooks.py", line 173, in webhook_cron_job
    await webhook.send(embed=embed)
  File "/usr/local/lib/python3.9/site-packages/discord/webhook/async_.py", line 1805, in send
    data = await adapter.execute_webhook(
  File "/usr/local/lib/python3.9/site-packages/discord/webhook/async_.py", line 121, in execute_webhook
    response = await self.session.request(
  File "/usr/local/lib/python3.9/site-packages/aiohttp/client.py", line 580, in _request
    await resp.start(conn)
  File "/usr/local/lib/python3.9/site-packages/aiohttp/client_reqrep.py", line 879, in start
    self._continue = True
RuntimeError: Task <Task pending name='Task-5651' coro=<webhook_cron_job() running at /app/backend/webhooks.py:173> cb=[run_until_complete.<locals>.done_cb()]>
got Future <Future pending> attached to a different loop

Upvotes: 0

Views: 91

Answers (0)

Related Questions