Django:每天在指定的用户本地时间运行一个进程 [英] Django: Running a process each day at specified user local time

查看:50
本文介绍了Django:每天在指定的用户本地时间运行一个进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要将网站移植到python/django,其中一个主要练习涉及一组数据,用户可以在该数据中安排本地时间并每天进行一次事件.

I'm porting my site to python/django, and one of the main exercises involves a set of data where users can schedule an event in their local time, and have it happen every day.

当前,我有一个cron作业(在另一台服务器上),该作业每5分钟启动一次方法,看看是否有什么事情需要在接下来的10分钟(比如说10分钟)内安排.

Currently i have a cron job (on another server) that hits up a method every e.g 5 minutes and see's if anything needs to be schedule over the next (let's say ) 10 minutes.

我存储一个时间值,以及每个作业的用户本地时区

I store a Time value, and the user's local timezone for each job

做到这一点的最佳方法是什么?

What is the best way to do this?

现在,我正在开发一个功能,该功能是:

Right now I am working on a function that:

  • 将服务器时间转换为用户本地时间.
  • 创建一个本地化的日期时间对象,该对象本地化为"today"和用户指定的时间
  • 检查是否在用户警报响起10分钟之内.
  • 如果介于23:50-23:59:59之间,并且用户的设置时间为00:00-00:10本地化的今天"是用明天"的日期创建的.(例如,如果距午夜2分钟,用户想在12:01,我用明天的日期计算事件)
  • 我设置了一个计划了last_scheduled字段,将last_fired字段设置为确保我不发送多个.

如果距现在10分钟以内,我安排了一个任务(线程等),该任务将很快触发.

If it is within 10 minutes from now, I schedule a task (thread, whatever) that will fire shortly.

不确定此处的最佳做法.我应该:
继续检查以查看我将来是否有任何工作,并安排短期任务吗?
提前预生成所有时间(可能是一个月一次)?
完全做其他事情吗?
我还以为我总是可以安排下一个"事件,但我担心的是,如果说我的服务器脱机,而我错过了下一个"事件,那么第二天就无法安排.

Not really sure on best practice here. Should I:
Keep checking to see if I have any in the future and scheduling short lived tasks?
Pre-generate all of my times ahead of time (maybe a month at a time?)
Do something else entirely?
I was also thinking I could always just schedule the "next" event, but My worry would be that if say my server went offline, and I missed the "next" event, the next day would never get scheduled.

澄清:

  • 我存储每个作业的时间和时区(例如,美国/美国东部时间中午).
  • 我正在校正DST,因此在计算UTC时间时,我将今天的日期用utc表示,将其转换为本地时间,然后使用该日期来计算增量.我正在使用pytz和normalize()来确保不会出现任何奇怪的DST问题.
  • 我确实有最后安排的时间,以确保我不会两次执行.

看下面的解决方案,我想我唯一的观察结果就是,如果由于某种原因我错过了预定的时间,我的下一个"将永远不会发生,因为那是过去的事情.我想我可以做一个第二个功能来修复所有错过的警报.

Looking at the solution below, I guess my only other observation is that if for whatever reason I missed a scheduled time, my "next" would never happen because it was then in the past. I suppose I could make a 2nd function to fix any missed alarms.

看完下面的答案后,我想到了以下较差的情况:

After grokking the answers below, I have come up with the following less-worse scenario:

我有以下字段

  • 上次事件执行时间
  • 上次活动已安排
  • 下一个事件执行时间
  • 一天中的时间和时区

每当我:更新事件或触发事件时,我都会计算并设置next_run_time.这将执行以下操作:

I Calculate and set next_run_time whenever I: Update the event, or fire the event. This does the following:

  • 如果它有最后一次运行时间,则将在未来至少2小时后计算next_run_time(通过添加一些填充来避免DST问题).
  • 如果事件从未执行过,请在未来至少安排15分钟(避免同时安排多个时间表)

我的预定作业执行以下操作:

My scheduled job does the following:

  1. 检查在接下来的15分钟内具有next_run_time且当前未安排的所有事件.计划进行任何匹配.

安排工作:

  • 安排任务,并按排定的现在"设置任务

任务执行时(成功):

  • last_run_time已更新为现在"
  • next_run_time重新计算

如果任务失败:-该作业将在30秒后重新安排.如果失败超过阈值(在我的情况下为3分钟),任务将中止,并在第二天重新计算next_run_time.这会记录下来,希望不会发生太多

If a task fails: - The job is rescheduled 30 seconds in the future. If failing beyond a threshold (3 minutes overdue in my case), the task is aborted and next_run_time is recalculated for the following day. This gets logged and hopefully doesn't happen too much

这似乎在大多数情况下都是有效的,因为我的活动总是(每天)进行,所以我有时间花些时间填充并避免一些毛茸茸的问题

This seems to mostly work because my events are always (daily), so I can afford to throw some padding in the times and avoid some hairy issues

推荐答案

我将保留Python/Django的特定细节,因为这不是我的专业领域.但通常来说,您正在描述的类型的任务计划程序应具有以下作用(IMHO):

I'll keep off the Python/Django specifics, since that's not my area of expertise. But in general, a task scheduler of the type you are describing should act as follows (IMHO):

  • 将时间表定义与执行时间分开
  • 时间表定义应在用户当地时间定义,并包括时区ID.
  • 执行时间应以UTC为单位.
  • 任务执行时,应从计划表中计算下一个执行时间.

我们来看一个例子.

  • 用户说:在美国东部时间每天晚上12点运行".
  • 我们存储的时间表为每天00:00, America/New_York ".
  • 我们将首次执行时间计算为 2013-06-30T04:00:00Z .
  • 使用任何喜欢的机制,在执行时运行作业.如果您定期轮询需要运行的作业,则只需查看时间是否已过去(ExecTime< = utcnow).如果您可以依靠事件系统,cron作业等,那可能更好.
  • 在作业运行时,使用计划表来计算下一个执行时间.
  • The user says, "Run every night at midnight, in US Eastern Time".
  • We store a schedule of "Daily, 00:00, America/New_York".
  • We calculate the first execution time to be 2013-06-30T04:00:00Z.
  • Using whatever mechanism you like, run the job at the execution time. If you are polling periodically for jobs that need running, just see if the time has passed (ExecTime <= utcnow). If you can rely on an eventing system, cron job, etc., that's probably better.
  • When the job runs, use the schedule to calculate the next execution time.

为什么要在当地时间安排时间?好吧,在美国东部时间,由于夏令时,它将在UTC的-5小时和-4小时之间转换.如果时间表严格基于UTC,则在DST过渡后,您会发现作业在用户认为错误的时间运行.

Why schedule in local time? Well, in the case of Eastern time, it will transition between -5 hours from UTC and -4 hours, because of Daylight Saving Time. If the schedule was strictly UTC based, then after the DST transition you'd find jobs running at what the user perceived to be the wrong time.

此外,您应该考虑处理故障,重试等.并且,您不希望该作业在每个计划执行中运行一次以上,因此,如果有的话,您可能希望有一种方法将其标记为处理中"多个程序检查任务.有时,您可能需要更复杂的锁定策略,以确保多个工作进程不会执行同一任务.这有点超出我在这里可以写的范围.

Also, you should think about handling failures, retries, etc. And you don't want the job to run more than once per scheduled execution, so you might want a way to mark it as "in process" if you have more than one program checking for tasks. Sometimes you might need a more complex locking strategy to ensure multiple worker processes don't pick up the same task. This is a bit beyond the scope of what I can write here.

您还应该考虑如何处理由夏令时过渡引起的本地时间歧义.考虑到后备"样式转换,如果用户说要在每晚1:30 AM"运行,但是一年中有一个晚上,1:30发生两次,您想做什么?如果您没有做任何特别的事情,它将在第一次出现时运行-通常是在白天.用户可能期望标准时间,因此您可能必须检查一下.即使您仅在午夜跑步,也不能免除此决定.有几个时区正好在午夜时分进行过渡(例如,巴西).

You should also think about how you want to handle ambiguities in local time caused by Daylight Saving Time transitions. Thinking about "fall-back" style transitions, if the user says to run at "1:30 AM every night", but there is one night a year where 1:30 happens twice, what do you want to do? If you do nothing special, it will run at the first occurrence - which is usually they daylight time. The user might expect the standard time, so you might have to check for this. Even if you just run at midnight, you're not exempt from this decision. There are several time zones that do their transition right at the stroke of midnight (Brazil, for example).

如果所有这些听起来都太麻烦了,那么您可能只想寻找已经编写的作业计划程序.例如,Java上的 Quartz APScheduler 的搜索,看上去很漂亮相似.

If all of this sounds like too much work, you might just want to look for a job scheduler that is already written. For example, Quartz on Java, or Quartz.Net on the .Net stack. I'm not directly familiar with it, but a search turned up APScheduler for Python, which looks pretty similar.

这篇关于Django:每天在指定的用户本地时间运行一个进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆