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

Inherited class is using methods from abstract parent with RedisJobStore #767

Closed
3 tasks done
555Russich opened this issue Aug 5, 2023 · 2 comments
Closed
3 tasks done
Labels

Comments

@555Russich
Copy link

555Russich commented Aug 5, 2023

Things to check first

  • I have checked that my issue does not already have a solution in the FAQ

  • I have searched the existing issues and didn't find my bug already reported there

  • I have checked that my bug is still present in the latest release

Version

3.10.1

What happened?

Expectation: Inherited class is using his own methods which must be implemented from abstract parent
Reality: Inherited class is using methods from abstract parent
Note: I notice this problem only with RedisJobStore

Error in logfile.log:

INFO:root:Scheduler started
INFO:root:Added job "MyAbstractClass.initiate_all" to job store "default"
INFO:root:Removed job 140d1c85738442748e98372ee0bd1a87
INFO:apscheduler.executors.default:Running job "MyAbstractClass.initiate_all (trigger: date[2023-08-05 11:51:07 MSK], next run at: 2023-08-05 11:51:07 MSK)" (scheduled at 2023-08-05 11:51:07.788467+03:00)
ERROR:apscheduler.executors.default:Job "MyAbstractClass.initiate_all (trigger: date[2023-08-05 11:51:07 MSK], next run at: 2023-08-05 11:51:07 MSK)" raised an exception
Traceback (most recent call last):
  File "/media/russich555/hdd/Programming/Freelance/YouDo/29.2pilot/venv/lib/python3.11/site-packages/apscheduler/executors/base_py3.py", line 30, in run_coroutine_job
    retval = await job.func(*job.args, **job.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/media/russich555/hdd/Programming/Freelance/YouDo/29.2pilot/mre/main.py", line 22, in initiate_all
    members = cls.get_required_members()
              ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/media/russich555/hdd/Programming/Freelance/YouDo/29.2pilot/mre/main.py", line 18, in get_required_members
    raise NotImplementedError
NotImplementedError

Same bug description on stackoverflow

How can we reproduce the bug?

from abc import ABC, abstractmethod
from datetime import datetime, timedelta
import asyncio
import logging

from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.jobstores.redis import RedisJobStore


logging.basicConfig(filename='logfile.log', level=logging.INFO)
logging.getLogger('apscheduler').setLevel(logging.DEBUG)


class MyAbstractClass(ABC):
    @classmethod
    @abstractmethod
    def get_required_members(cls):
        raise NotImplementedError

    @classmethod
    async def initiate_all(cls):
        members = cls.get_required_members()
        logging.info(f'Got {members=}')
        ...


class MyImplementation(MyAbstractClass):
    @classmethod
    def get_required_members(cls):
        return ['Alex', 'Anna']

    @classmethod
    def append_to_scheduler(cls, scheduler: AsyncIOScheduler, run_date: datetime):
        return scheduler.add_job(
            func=cls.initiate_all,
            trigger='date',
            run_date=run_date
        )


redis_job_store = RedisJobStore()
scheduler = AsyncIOScheduler(jobstores={'default': redis_job_store}, logger=logging.getLogger())
scheduler.start()

run_date = datetime.now() + timedelta(seconds=5)
MyImplementation.append_to_scheduler(scheduler=scheduler, run_date=run_date)
asyncio.get_event_loop().run_forever()

Workaround I use for now: pass to initiate_all child class as argument

class MyAbstractClass(ABC):
    @classmethod
    async def initiate_all(cls, child_class):
        members = child_class.get_required_members()
        logging.info(f'Got {members=}')
        ...

class MyImplementation(MyAbstractClass):
    @classmethod
    def append_to_scheduler(cls, scheduler: AsyncIOScheduler, run_date: datetime):
        return scheduler.add_job(
            func=cls.initiate_all,
            kwargs={'child_class': cls},
            trigger='date',
            run_date=run_date
        )

Expected output:

INFO:root:Scheduler started
INFO:root:Added job "MyAbstractClass.initiate_all" to job store "default"
INFO:root:Removed job d289c9dfbad2481b99585b4de0ae6cff
INFO:apscheduler.executors.default:Running job "MyAbstractClass.initiate_all (trigger: date[2023-08-05 11:55:39 MSK], next run at: 2023-08-05 11:55:39 MSK)" (scheduled at 2023-08-05 11:55:39.280433+03:00)
INFO:root:Got members=['Alex', 'Anna']
INFO:apscheduler.executors.default:Job "MyAbstractClass.initiate_all (trigger: date[2023-08-05 11:55:39 MSK], next run at: 2023-08-05 11:55:39 MSK)" executed successfully
@555Russich 555Russich added the bug label Aug 5, 2023
@555Russich
Copy link
Author

One smart guy on stackoverflow patched apscheduler.util.get_callable_name and it solved my issue. Probably it should be implemented in master branch?

@agronholm
Copy link
Owner

Fixed via 71c7d95.

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

No branches or pull requests

2 participants