3

I wanted to use the ready() hook in my AppConfig to start django-rq scheduler job. However it does so multiple times, every times I start the server. I imagine that's due to threading however I can't seem to find a suitable workaround. This is my AppConfig:

class AnalyticsConfig(AppConfig):
    name = 'analytics'

    def ready(self):
        print("Init scheduler")
        
        from analytics.services import save_hits
        scheduler = django_rq.get_scheduler('analytics')
        scheduler.schedule(datetime.utcnow(), save_hits, interval=5)
        

Now when I do runserver, Init scheduler is displayed 3 times. I've done some digging and according to this question I started the server with --noreload which didn't help (I still got Init scheduler x3). I also tried putting

import os

if os.environ.get('RUN_MAIN', None) != 'true':
    default_app_config = 'analytics.apps.AnalyticsConfig'

in my __init__.py however RUN_MAIN appears to be None every time.

Afterwards I created a FileLock class, to skip configuration after the first initialization, which looks like this:

class FileLock:
    def __get__(self, instance, owner):
        return os.access(f"{instance.__class__.__name__}.lock", os.F_OK)

    def __set__(self, instance, value):
        if not isinstance(value, bool):
            raise AttributeError

        if value:
            f = open(f"{instance.__class__.__name__}.lock", 'w+')
            f.close()
        else:
            os.remove(f"{instance.__class__.__name__}.lock")

    def __delete__(self, obj):
        raise AttributeError

class AnalyticsConfig(AppConfig):
    name = 'analytics'
    locked = FileLock()

    def ready(self):
        from analytics.services import save_hits

        if not self.locked:
            print("Init scheduler")
            scheduler = django_rq.get_scheduler('analytics')
            scheduler.schedule(datetime.utcnow(), save_hits, interval=5)

            self.locked = True

This does work, however the lock is not destroyed after the app quits. I tried removing the .lock files in settings.py but it also runs multiple times, making this pointless.

My question is: How can I prevent django from calling ready() multiple times, or how otherwise can I teardown the .lock files after django exits or right after it boots?

I'm using python 3.8 and django 3.1.5

MilyMilo
  • 121
  • 1
  • 6

0 Answers0