Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Cannot use local time for cron schedules and UTC for solar schedules #57
To make Solar scheduling work I had to set CELERY_TIMEZONE = 'UTC' - however this causes Crontab schedules to be offset by my timezone .
That means a crontab configured trigger in 1 hour's time does not end up triggering for 11 hours (because I am in +10 Australia/Brisbane).
Should django-celery-beat create crontab schedules with CrontabSchedule.tz = settings.TIME_ZONE instead to override CELERY_TIMEZONE?
This is related to #49
Giving the ability to configure
But in the meantime defaulting to using
At the moment the existing behaviour is useless for the vast majority of people, so at least having a sane default is a considerable upgrade.
Hey there @DDevine , Thanks for the research. I'll be hacking around to implement your workaround until this gets fixed the right way. Could you tell me exactly where in the from_entry line to put the nowfun arg? I'll be working on it tonight so I may get to it before you respond...but I may also get lost:).
I just got bit by this messing with my crontab tasks when I turned the timezone to the proper timezone instead of UTC
I've looked into it some more, I've found it a bit tricky to debug and to wrap my head around all the timezone stuff. There's a lot more problems, particularly where Solar is concerned - I'm not convinced it was ever tested before being added to Celery...
This allows Celery to process the crontab in context of your local time - assuming that you have Django TIME_ZONE set to your local time. This is probably not the right way to do it - but I am just hacking at this problem for the moment.
Pytz is creating a LMT based timezone for Australia/Brisbane (+10:12 LMT) rather than a clean UTC offset (10:00 UTC) or tomezone abbreviation (... AEST). LMT does not cleanly convert to UTC and I found that when converting using pytz
For example, in the
It also seems that when there are Crontab schedules are not checked/executed while there are Solar schedules. Awesome...
Another problem is that I notice the delta goes negative. This issue is dealt with in the
It also seems that upon restarting celerybeat solar tasks that have already been run are also run again... Maybe this is an issue with
The whole lot is a mess. I really didn't anticipate this trouble!
Holy Cow....You weren't kidding about tricky.
I dove in deep last night and...bleh.
So (separate bug), Celery is not properly taking django's TIME_ZONE setting like it says it will and it tries to do. It simply doesn't see django's timezone variable for some reason. So I had to explicitly set celey's timezone like you did.
You are right about the LMT thing. That would have driven me crazy had you not mentioned it. I wonder why it does that-->https://stackoverflow.com/questions/11473721/weird-timezone-issue-with-pytz.
I tracked a lot of the handling and just figured I could provide 'app=self.app' to some constructors since a lot of the is_due() stuff is mediated by ModelEntry.
But it looks like you know the problem I ran into next....a lot of the other calculations (remaining_delta, remaining_time etc)don't use app.now() directly and so I end up with offsets that are off. It does look like nowfun is the way to go...but I was looking for a way to not touch the django model itself.
Perhaps I still can go with using app.now() properly....looking into it more later. I spent a good deal of time last night hacking around celery, django-celery-beat, and my app tracing exactly where and how things are called.
I adjusted my debug statements a little and found that crontab was using
The question is - what is the real issue here? Is there more than one? Do we need to detect funky LMT datetimes and handle them over in celery? Does Celery try to use Django's TIME_ZONE? I was under the impression that Celery did not try to directly use Django's TIME_ZONE variable - and from what I can tell CELERY_TIMEZONE from within Django does seem to work. Were you getting confused between TIME_ZONE and CELERY_TIMEZONE?
referenced this issue
Jul 7, 2017
From Celery's Periodic Tasks Notes
But it lies:).
Btw thanks for this investigation and the work to fix.
This was referenced
Jul 7, 2017
referenced this issue
Jul 24, 2017
I was forced to look back into this - I have no idea why my other code was working in my development machine but is not working in new installs!
I traced it down to what you alluded to @JoshYuJump - your fix is not the most correct, but it is on the right track.
celery.app.base.now() was returning a PyTZ timezone, which Celery should use - however it does not make sense in the Django Celery Beat context. I think that's what the PyTZ Introduction section is alluding to (http://pytz.sourceforge.net/#introduction) however whenever I look at the PyTZ documentation my eyes instantly glaze over.
Anyway - for Django Celery Beat we need to localize self.app.now() in schedulers.ModelEntry._default_now().
I'll look testing my fix further tomorrow and submit a PR.
Without this #68 doesn't work.
This was really goofy, but what I did was override the celery base app's
class MyCelery(Celery) def now(self): """Return the current time and date as a datetime.""" from datetime import datetime return datetime.now(self.timezone) app = MyCelery()
And this fixed the issue for us. n.b., this issue may be fixed in the master branch, but it may not be the wisest decision to rely upon version 4.X getting timezones right anytime soon.