Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timeout for pending jobs raises InvalidStateError #67

Open
Zeniuus opened this issue Oct 19, 2018 · 2 comments
Open

Timeout for pending jobs raises InvalidStateError #67

Zeniuus opened this issue Oct 19, 2018 · 2 comments

Comments

@Zeniuus
Copy link

Zeniuus commented Oct 19, 2018

Environment:

  • macOS HighSierra 10.13.6
  • Python v3.6.6 with pyenv
  • aiojobs v0.2.2

How to reproduce:

import asyncio

import aiojobs


async def some_unexpectedly_long_async_job():
    await asyncio.sleep(10000)


async def reproduce_bug():
    scheduler = await aiojobs.create_scheduler(limit=1)

    jobs = await asyncio.gather(*[scheduler.spawn(some_unexpectedly_long_async_job())
                                  for _ in range(2)])
    try:
        waited_jobs = await asyncio.gather(*[job.wait(timeout=3) for job in jobs])
    except:
        # Deal with async jobs timeout
        pass

    await scheduler.close()

loop = asyncio.get_event_loop()
loop.run_until_complete(reproduce_bug())

bug:

Exception in callback Job._done_callback(<Task cancell...at test.py:6>>)
handle: <Handle Job._done_callback(<Task cancell...at test.py:6>>)>
Traceback (most recent call last):
  File "/Users/zeniuus/.pyenv/versions/3.6.6/lib/python3.6/asyncio/events.py", line 145, in _run
    self._callback(*self._args)
  File "/Users/zeniuus/.pyenv/versions/aiojobs-bug-test/lib/python3.6/site-packages/aiojobs/_job.py", line 138, in _done_callback
    scheduler._done(self)
  File "/Users/zeniuus/.pyenv/versions/aiojobs-bug-test/lib/python3.6/site-packages/aiojobs/_scheduler.py", line 141, in _done
    new_job._start()
  File "/Users/zeniuus/.pyenv/versions/aiojobs-bug-test/lib/python3.6/site-packages/aiojobs/_job.py", line 134, in _start
    self._started.set_result(None)
asyncio.base_futures.InvalidStateError: invalid state
@Zeniuus
Copy link
Author

Zeniuus commented Oct 19, 2018

I tested with various cases and I found that this error occurs when

  1. # of jobs is bigger than # of job limit of the scheduler so that there exists a pending job, and
  2. the pending job's coroutine does not start until its timeout given by param.

I was able to fix this error by fixing Job::_do_wait as below.
Original:

    async def _do_wait(self, timeout):
        with async_timeout.timeout(timeout=timeout, loop=self._loop):
            # TODO: add a test for waiting for a pending coro
            await self._started
            result = await self._task
            return result

Fixed:

    async def _do_wait(self, timeout):
        with async_timeout.timeout(timeout=timeout, loop=self._loop):
            # TODO: add a test for waiting for a pending coro
            try:
                await self._started
            except:
                self._closed = True
                raise
            result = await self._task
            return result

@Zeniuus Zeniuus changed the title Timeout for pending jobs generates InvalidStateError Timeout for pending jobs raises InvalidStateError Oct 19, 2018
henworth added a commit to henworth/aiojobs that referenced this issue Dec 3, 2019
@Dreamsorcerer
Copy link
Member

It would be great if you could verify the problem still exists on master, and create a test in a PR that reproduces the issue if still present.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants