Seeking ideas for a cron implementation

Discussion in 'Python' started by Karthik Gurusamy, Aug 22, 2008.

  1. Hi,

    I'm working on a cron like functionality for my application.
    The outer loops runs continuously waking every x seconds (say x=180,
    300, ..).
    It needs to know what events in cron has expired and for each event do
    the work needed.

    It's basically like unix cron or like a calendar application with some
    restrictions. The outer loop may come back a lot later and many events
    might have missed their schedule -- but this is okay.. We don't have
    to worry about missed events (if there were n misses, we just need to
    execute call back once).

    Let's take some examples [Let e denotes an event]
    e1: hour=1 min=30 # Run every day once at
    1:30 AM
    e2: wday=0, hour=1 min=0 # run every Monday at 1 AM
    e3: month=10, day=10, hour=10 min=0 # run on October 10th, 10 AM
    every year

    class Cron_Event (object):
    def __init__ (year=None, month=None, day=None, hour=None ..etc)
    # do init

    class Cron (object):
    def __init__ ():
    # do init
    def event_add (e):
    # add an event
    def execute()
    # see if any events has "expired" .. call it's callback
    # I'm looking for ideas on how to manage the events here

    From outer loop
    cron = Cron()
    # create various events like
    e1 = Cron_Event(hour=1)
    cron.event_add(e1)
    e2 = Cron_Event(wday=0, hour=1)
    cron.event_add(e2)

    while True:
    sleep x seconds (or wait until woken up)
    cron.execute()
    # do other work.. x may change here

    If I can restrict to hour and minute, it seems manageable as the
    interval between two occurrences is a constant. But allowing days like
    every Monday or 1st of every month makes things complicated. Moreover
    I would like each constraint in e to take on multiple possibilities
    (like every day at 1AM, 2 AM and 4 AM do this).

    I'm looking for solutions that can leverage datetime.datetime
    routines.
    My current ideas include for each e, track the next time it will fire
    (in seconds since epoch as given by time.time()). Once current time
    has passed that time, we execute the event. e.g.
    >>> datetime.datetime.now()

    datetime.datetime(2008, 8, 22, 13, 19, 54, 5567)
    >>> time.time()

    1219436401.741966 <--- compute event's next firing in a format like
    this
    >>>


    The problem seems to be how to compute that future point in time (in
    seconds since epoch) for a generic Cron_Event.

    Say how do I know the exact time in future that will satisfy a
    constraint like:
    month=11, wday=1, hour=3, min=30 # At 3:30 AM on a Tuesday in
    November

    Thanks for your thoughts.

    Karthik
     
    Karthik Gurusamy, Aug 22, 2008
    #1
    1. Advertising

  2. Karthik Gurusamy

    Sean DiZazzo Guest

    On Aug 22, 1:30 pm, Karthik Gurusamy <> wrote:
    > Hi,
    >
    > I'm working on a cron like functionality for my application.
    > The outer loops runs continuously waking every x seconds (say x=180,
    > 300, ..).
    > It needs to know what events in cron has expired and for each event do
    > the work needed.
    >
    > It's basically like unix cron or like a calendar application with some
    > restrictions. The outer loop may come back a lot later and many events
    > might have missed their schedule -- but this is okay.. We don't have
    > to worry about missed events (if there were n misses, we just need to
    > execute call back once).
    >
    > Let's take some examples [Let e denotes an event]
    > e1: hour=1  min=30                             # Run every day once at
    > 1:30 AM
    > e2: wday=0, hour=1  min=0                   # run every Monday at 1 AM
    > e3: month=10, day=10, hour=10 min=0  # run on October 10th, 10 AM
    > every year
    >
    > class Cron_Event (object):
    >     def __init__ (year=None, month=None, day=None, hour=None ...etc)
    >       #  do init
    >
    > class Cron (object):
    >     def __init__ ():
    >         # do init
    >     def event_add (e):
    >         # add an event
    >     def execute()
    >         # see if any events has "expired" .. call it's callback
    >         # I'm looking for ideas on how to manage the events here
    >
    > From outer loop
    > cron = Cron()
    > # create various events like
    > e1 = Cron_Event(hour=1)
    > cron.event_add(e1)
    > e2 = Cron_Event(wday=0, hour=1)
    > cron.event_add(e2)
    >
    > while True:
    >     sleep x seconds (or wait until woken up)
    >     cron.execute()
    >     # do other work.. x may change here
    >
    > If I can restrict to hour and minute, it seems manageable as the
    > interval between two occurrences is a constant. But allowing days like
    > every Monday or 1st of every month makes things complicated. Moreover
    > I would like each constraint in e to take on multiple possibilities
    > (like every day at 1AM,  2 AM and 4 AM do this).
    >
    > I'm looking for solutions that can leverage datetime.datetime
    > routines.
    > My current ideas include for each e, track the next time it will fire
    > (in seconds since epoch as given by time.time()). Once current time
    > has passed that time, we execute the event. e.g.>>> datetime.datetime.now()
    >
    > datetime.datetime(2008, 8, 22, 13, 19, 54, 5567)>>> time.time()
    >
    > 1219436401.741966    <--- compute event's next firing in a format like
    > this
    >
    >
    >
    > The problem seems to be how to compute that future point in time (in
    > seconds since epoch)  for a generic Cron_Event.
    >
    > Say how do I know the exact time in future  that will satisfy a
    > constraint like:
    >  month=11, wday=1, hour=3, min=30    # At 3:30 AM on a Tuesday in
    > November
    >
    > Thanks for your thoughts.
    >
    > Karthik


    I only scanned your message, but maybe datetime.timedelta() will
    help..

    >>> import datetime
    >>> now = datetime.datetime.now()
    >>> print now

    2008-08-22 13:48:49.335225
    >>> day = datetime.timedelta(1)
    >>> print day

    1 day, 0:00:00
    >>> print now + day

    2008-08-23 13:48:49.335225

    ~Sean
     
    Sean DiZazzo, Aug 22, 2008
    #2
    1. Advertising

  3. On Aug 22, 1:51 pm, Sean DiZazzo <> wrote:
    > On Aug 22, 1:30 pm, Karthik Gurusamy <> wrote:
    >
    >
    >
    > > Hi,

    >
    > > I'm working on acronlike functionality for my application.
    > > The outer loops runs continuously waking every x seconds (say x=180,
    > > 300, ..).
    > > It needs to know what events incronhas expired and for each event do
    > > the work needed.

    >
    > > It's basically like unixcronor like a calendar application with some
    > > restrictions. The outer loop may come back a lot later and many events
    > > might have missed their schedule -- but this is okay.. We don't have
    > > to worry about missed events (if there were n misses, we just need to
    > > execute call back once).

    >
    > > Let's take some examples [Let e denotes an event]
    > > e1: hour=1  min=30                             # Run every day once at
    > > 1:30 AM
    > > e2: wday=0, hour=1  min=0                   # run every Monday at 1 AM
    > > e3: month=10, day=10, hour=10 min=0  # run on October 10th, 10 AM
    > > every year

    >
    > > class Cron_Event (object):
    > >     def __init__ (year=None, month=None, day=None, hour=None ..etc)
    > >       #  do init

    >
    > > classCron(object):
    > >     def __init__ ():
    > >         # do init
    > >     def event_add (e):
    > >         # add an event
    > >     def execute()
    > >         # see if any events has "expired" .. call it's callback
    > >         # I'm looking for ideas on how to manage the events here

    >
    > > From outer loop
    > >cron=Cron()
    > > # create various events like
    > > e1 = Cron_Event(hour=1)
    > >cron.event_add(e1)
    > > e2 = Cron_Event(wday=0, hour=1)
    > >cron.event_add(e2)

    >
    > > while True:
    > >     sleep x seconds (or wait until woken up)
    > >    cron.execute()
    > >     # do other work.. x may change here

    >
    > > If I can restrict to hour and minute, it seems manageable as the
    > > interval between two occurrences is a constant. But allowing days like
    > > every Monday or 1st of every month makes things complicated. Moreover
    > > I would like each constraint in e to take on multiple possibilities
    > > (like every day at 1AM,  2 AM and 4 AM do this).

    >
    > > I'm looking for solutions that can leverage datetime.datetime
    > > routines.
    > > My current ideas include for each e, track the next time it will fire
    > > (in seconds since epoch as given by time.time()). Once current time
    > > has passed that time, we execute the event. e.g.>>> datetime.datetime.now()

    >
    > > datetime.datetime(2008, 8, 22, 13, 19, 54, 5567)>>> time.time()

    >
    > > 1219436401.741966    <--- compute event's next firing in a format like
    > > this

    >
    > > The problem seems to be how to compute that future point in time (in
    > > seconds since epoch)  for a generic Cron_Event.

    >
    > > Say how do I know the exact time in future  that will satisfy a
    > > constraint like:
    > >  month=11, wday=1, hour=3, min=30    # At 3:30 AM on a Tuesday in
    > > November

    >
    > > Thanks for your thoughts.

    >
    > > Karthik

    >
    > I only scanned your message, but maybe datetime.timedelta() will
    > help..
    >
    > >>> import datetime
    > >>> now = datetime.datetime.now()
    > >>> print now

    >
    > 2008-08-22 13:48:49.335225>>> day = datetime.timedelta(1)
    > >>> print day

    > 1 day, 0:00:00
    > >>> print now + day

    >
    > 2008-08-23 13:48:49.335225


    Thanks, I found using a more efficient algorithm tricky and seemed
    error prone.
    [I do welcome ideas still if anyone has a cool solution]

    I used your idea and took the easy way out by using a brute-force
    search.

    Here is an outline if anyone faces similar problem:
    hours, minutes are lists: say for every day at 1:30 pm and 2:45 pm,
    hours=[13, 14] and minutes=[30, 45,].
    I restricted myself to minutes and hours (and every day) to simplify
    the problem.

    def set_expiry_time_check_in_a_day (self, now, target,
    hours, mins, flags=set()):
    """
    A small utility routine to simulate 'goto'
    Looks like now could be computed inside this function --
    the small
    drift due to time taken in this function should be
    negligible
    """
    # let's see if in today we can find an expiry
    # we do brute force search starting with the smallest hour
    for hour in hours:
    for min in mins:
    target = target.replace(hour=hour, minute=min,
    second=0,
    microsecond=0)
    if 'is_debug_1' in flags:
    print "Trying target time: %s..." % target
    if target > now:
    if 'is_debug_1' in flags:
    print "Found target time: %s" % (target, )
    return target # simulates a break from two loops
    return None

    def set_expiry_time (self, event, flags=set()):
    """
    For a given event, compute and remember when it will fire
    next
    """
    now = datetime.datetime.now()

    target = now # start checking from now..

    # assumption, hours and mins are atleast one int element array
    # and they are in sorted order
    hours = event.spec['hours']
    mins = event.spec['minutes']

    tries = 0
    while True: # runs of each day.. tomorrow ...
    tries += 1
    if tries > 50: # safety valve, we are basically in
    infinite loop
    raise Exception("Tried 50 times.. in infinite loop??")

    target_found = self.set_expiry_time_check_in_a_day(now,
    target,
    hours, mins, flags)

    if target_found is not None: # found a match on "this" day
    target = target_found
    break

    # we need to increase the day count..
    increment = datetime.timedelta(days=1)
    target += increment
    # added 24 hours .. let's go and check tomorrow ...

    event.target = target



    >
    > ~Sean
     
    Karthik Gurusamy, Sep 7, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andrew Banks

    Equiv of a CRON job?

    Andrew Banks, Apr 8, 2004, in forum: ASP .Net
    Replies:
    8
    Views:
    15,253
    PeteJ
    Jul 30, 2012
  2. Mr. T

    Timer vs. Cron Jobs

    Mr. T, Jun 9, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    736
    Hans Kesting
    Jun 9, 2004
  3. Bubba
    Replies:
    24
    Views:
    675
    Joe keane
    Jan 18, 2012
  4. Kirk Haines
    Replies:
    8
    Views:
    146
    Robert Klemme
    Aug 13, 2004
  5. Replies:
    6
    Views:
    143
Loading...

Share This Page