Forum: Ruby Cute little simple scheduling code hack

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
138a92dc140be1f1c8dfbf890822f160?d=identicon&s=25 KCons (Guest)
on 2007-02-23 07:36
(Received via mailing list)
I'm sure there is some far superior prior art out there somewhere, but
this is a useful little hack I threw together today that I thought
someone else might find interesting.

I wanted to do a little task every few seconds for some duration of
time, and after a bit of overkill I came up with a little library that
lets me do stuff like:

every( 5.seconds ).for( 2.days ) { puts "Chunky bacon, k?" }

or

every( 2.minutes ).until ( Time.now + 4.hours ) { dance_for_a_while }

or even

class String
  def gradual_out( n = 1 )
   ix = 0
   every( n.seconds ).unless(lambda {ix >= size}) do
     print self[ix].chr
     ix += 1
   end
  end
end

"Tuesday is the new Thursday".gradual_out( 400.milliseconds )


Fun to play with.
Again, just a quick hack, so if you see any glaring issues or useful
improvements, let me know, because I'm sure I'll find use for it again
later.

--Code below--

class Scheduler
  def initialize( int )
    @interval = int
  end

  def for( secs )
    self.until( Time.now + secs ) { |x| yield x }
  end

  def until( endtime )
    self.unless( lambda { Time.now >= endtime } ) { |x| yield x }
  end

  def unless( cond )
    while !cond.call do
      current = Time.now
      yield current
      wait_time = (current + @interval) - Time.now
      begin
        sleep( wait_time ) unless wait_time <= 0 or cond.call
      rescue Interrupt
        break
      end
    end
  end
end

module Kernel
  def every( int )
    Scheduler.new( int )
  end
end

class Numeric
  def seconds; self; end
  def minutes; self * 60; end
  def hours; self.minutes * 60; end
  def milliseconds; self / 1000.0; end
  def days; self.hours * 24; end
end
F9c5973e7d1eb451754426dfe955fb59?d=identicon&s=25 John Mettraux (Guest)
on 2007-02-23 08:10
(Received via mailing list)
2007/2/23, KCons <consalus@gmail.com>:
> or
>      ix += 1
>    end
>   end
> end
>
> "Tuesday is the new Thursday".gradual_out( 400.milliseconds )

Hi,

I had come up with that :

http://openwferu.rubyforge.org/scheduler.html

advantage : one thread for all the tasks
disadvantage : has to wake up to pool its jobqueue


But your approach is definitely more cute and more 'rubystic'.

Quick question : is the "rescue Interrupt" really needed ? Does it
avoid some "under the carpet thread problems" ?


Best regards,
138a92dc140be1f1c8dfbf890822f160?d=identicon&s=25 KCons (Guest)
on 2007-02-23 08:35
(Received via mailing list)
>
> I had come up with that :
>
> http://openwferu.rubyforge.org/scheduler.html
>

Neat, that'll certainly come in handy when I'm doing more complicated
scheduling.
Clean interface, too.


> Quick question : is the "rescue Interrupt" really needed ? Does it
> avoid some "under the carpet thread problems" ?
Y'know, I imagine the 'rescue Interrupt' business is not actually
needed. It is just there because I got seeing exception dumps when I
Ctrl-C'd out of the sleep. :)
C742175a04e90db217deaf3650ef5d30?d=identicon&s=25 Michael Brooks (Guest)
on 2007-02-23 08:55
(Received via mailing list)
KCons wrote:
> or
>      ix += 1
> later.
>
<snip>

Hello KCons:

Wow... I'm just (8 hours into both) learning Python and Ruby and I
didn't realize how powerful / extensible Ruby was until I saw your
example.  Great stuff!

Thanks,

Michael
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2007-02-23 16:43
(Received via mailing list)
On Fri, 23 Feb 2007, John Mettraux wrote:

> Hi,
>
> I had come up with that :
>
> http://openwferu.rubyforge.org/scheduler.html

looks very interesting!

> advantage : one thread for all the tasks disadvantage : has to wake up to
> pool its jobqueue

hmmm.  is that even possible?


     harp :~/openwferu/trunk/openwfe-ruby > cat a.rb
     require "time"
     require "openwfe/util/otime"
     require "openwfe/util/scheduler"
     include OpenWFE

     scheduler = Scheduler.new

     i = -1

     scheduler.schedule('*/1 * * * *') do
       4.times{ puts Time.now.iso8601(2); sleep 30 }  ### this takes
120s!
       puts(i += 1)
     end

     scheduler.sstart

     STDIN.gets



     harp :~/openwferu/trunk/openwfe-ruby > RUBYLIB=lib ruby a.rb
     2007-02-23T08:29:00.22-07:00
     2007-02-23T08:29:30.22-07:00
     2007-02-23T08:30:00.22-07:00
     2007-02-23T08:30:30.22-07:00
     0
     2007-02-23T08:31:00.47-07:00
     2007-02-23T08:31:30.47-07:00
     2007-02-23T08:32:00.47-07:00
     2007-02-23T08:32:30.47-07:00
     1
     2007-02-23T08:33:00.73-07:00
     2007-02-23T08:33:30.73-07:00
     2007-02-23T08:34:00.73-07:00
     2007-02-23T08:34:30.73-07:00
     2
     2007-02-23T08:35:00.98-07:00
     2007-02-23T08:35:30.98-07:00
     2007-02-23T08:36:00.98-07:00
     2007-02-23T08:36:30.98-07:00
     3
     2007-02-23T08:38:00.23-07:00
     2007-02-23T08:38:30.23-07:00
     ...
     ...
     ...

it seems like a single threaded/processed scheduler is an imposibility?

nevertheless i've already found a use for this code in a situation where
i
don't care if events are fired precisely (as is possible) as i declare
them or
not.

cheers.

-a
F9c5973e7d1eb451754426dfe955fb59?d=identicon&s=25 John Mettraux (Guest)
on 2007-02-23 23:53
(Received via mailing list)
2007/2/24, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov>:
>
>
>
>      harp :~/openwferu/trunk/openwfe-ruby > RUBYLIB=lib ruby a.rb
>      2007-02-23T08:29:00.22-07:00
>      2007-02-23T08:29:30.22-07:00
>      2007-02-23T08:30:00.22-07:00
>      2007-02-23T08:30:30.22-07:00
>      0
> ...
>
> it seems like a single threaded/processed scheduler is an imposibility?

Hey, thanks for the light, I'll fix that / make it better.

I'll have to correct from "one thread for all tasks" to something like
"one thread as an alarm clock for all tasks".


> nevertheless i've already found a use for this code in a situation where i
> don't care if events are fired precisely (as is possible) as i declare them or
> not.

Glad to read that.


Cheers,
C9c7a65848f13e2b1a226bbe43bc3672?d=identicon&s=25 Pete Yandell (pete)
on 2007-02-26 08:59
(Received via mailing list)
On 23/02/2007, at 5:35 PM, KCons wrote:

> I'm sure there is some far superior prior art out there somewhere, but
> this is a useful little hack I threw together today that I thought
> someone else might find interesting.

It is interesting! You need to blog about it somewhere so I can
bookmark it for later. :)

Pete Yandell
http://notahat.com/
This topic is locked and can not be replied to.