Class: Event
- Inherits:
-
Object
- Object
- Event
- Includes:
- Comparable
- Defined in:
- lib/event.rb,
lib/event/at.rb,
lib/event/every.rb,
lib/event/timed.rb
Overview
Description
Allows to schedule things (furtherly called ‘events’) in one of several ways. Scheduled provides the methods to determine when this event will be executed next, when it was executed previuosly or how many seconds are left until the next execution. If a block is provided at creation it will execute that block everytime the event is due.
Synopsis
# calls go_check_mails every 10 minutes, starting in 1h, ending 24h later
check_mail_event = Event.every(600, :start => Time.now+3600, :stop => Time.now+90000) { |event|
go_check_mails(...)
}
# deactivate it for the next 30 minutes
# be aware only calling on/off will leave the Scheduled#next the same
check_mail_event.off
sleep(30*60)
# avoid that after 'on' the block get's called as many times as it was missed due to off
check_mail_event.postpone
# reactivate the check_mail_event
check_mail_event.on
# let the mail checking be done 15s earlier this time
check_mail_event.alter(-15)
# see how many seconds are left to the next event
puts check_mail_event.seconds_left.to_s
# let's the current thread sleep until check_mail_event is finished.
check_mail_event.join
# this will be due? every hour, at minute 1, 2, 3, 4, 5, at seconds 0 and 30.
# see Scheduled.timed for more information
cron_like = Scheduled.timed("*", (1..5), [0, 30]) { |event| ...do something... }
# this one will be due? every given
specific_times = Scheduled.at(Time.now+86400, Time.now+3600, Time.now+60)
# take a break at 09.15, 10.15, 11.15, 13.15, 14.15 and 15.15
takeBreak = Scheduled.timed([9,10,11,13,14,15], [15])
Defined Under Namespace
Constant Summary collapse
- HOUR_DIVISORS =
[1, 2, 3, 4, 6, 8, 12, 24]
- MINUTE_DIVISORS =
[1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60]
- SECOND_DIVISORS =
MINUTE_DIVISORS
Instance Attribute Summary collapse
-
#count ⇒ Object
readonly
Integer, counting how many times one_done was called.
-
#next ⇒ Object
readonly
Time object containing the time when the event is due next Will be nil if there’s no next event possible to schedule (technically, not due to the event being finished, over stop or over times).
-
#previous ⇒ Object
readonly
Time object containing the time when the event was due the las time.
-
#scheduler ⇒ Object
:nodoc: FIXME, make it foolproof (no change of responsible scheduler).
-
#start ⇒ Object
readonly
Time after which the event will be scheduled.
-
#stop ⇒ Object
readonly
Time after which the event won’t be scheduled anymore.
-
#times ⇒ Object
readonly
Integer or nil, containing how many times the event will be due.
Class Method Summary collapse
-
.at(*datetimes, &block) ⇒ Object
Creates a Schedule that is invoked at specified datetimes.
-
.every(seconds, options = {}, &block) ⇒ Object
Creates a Schedule which is invoked in an interval, every <seconds> seconds.
-
.timed(hours = [0], minutes = [0], seconds = [0], options = {}, &block) ⇒ Object
Creates a Schedule which is invoked at specified hours, minutes and seconds of a day.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
returns -1, 0 or 1 (smaller, equal to, bigger then other) nil-values for seconds_left are treaded like +INF <=> is overloaded, returning for * Event: self.seconds_left <=> other.seconds_left (anything responding to .seconds_left) * Time: self.next <=> other (only instances of Time, not Date nor DateTime) * Numeric: self.to_f <=> other.to_f (anything responding to .to_f).
-
#alter(by_seconds = 0) ⇒ Object
alterates the next-time exactly by “by_seconds”, doesn’t influence anything else.
-
#call(*args) ⇒ Object
Invoke the event.
-
#due?(time = nil) ⇒ Boolean
Whether Scheduled event is due now.
-
#extract_time_range(range, rangeEnd, divisors) ⇒ Object
Normalizes inputs like “*”, “1/12”, 12, [1, 13], (1..5) to an array of all corresponding integers.
-
#finished ⇒ Object
Define the Event as finished and remove it from the scheduler (if scheduled).
-
#finished? ⇒ Boolean
Whether an event has been declared as finished or not.
-
#initialize(options = {}, &block) ⇒ Event
constructor
Don’t use directly, use the creation methods.
-
#join ⇒ Object
Stop current thread until this event is finished.
-
#off ⇒ Object
Switch the Scheduled event off.
-
#off? ⇒ Boolean
Whether an event has been switched off (see Scheduled#off).
-
#on ⇒ Object
Switch the Scheduled event on.
-
#on? ⇒ Boolean
Whether an event has been switched on (default).
-
#one_done(increment = true) ⇒ Object
Increment @count by one and return @next or nil if event is finished.
-
#reschedule(by_seconds = 0, postpone_stop = true) ⇒ Object
(also: #postpone)
Will reinitalize the Scheduled event with start time beeing the current time.
-
#seconds_left(time = nil) ⇒ Object
returns seconds left until next Timed returns nil if event is past @stop-datetime returns nil if event has been processed the specified amount of times.
-
#times_left ⇒ Object
returns how many times the event still has to be executed.
-
#to_f ⇒ Object
The left time to next due? as float.
-
#to_i ⇒ Object
The left time to next due? as integer.
- #update_scheduler ⇒ Object
Constructor Details
#initialize(options = {}, &block) ⇒ Event
Don’t use directly, use the creation methods.
115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/event.rb', line 115 def initialize(={}, &block) # :nodoc: @block = block @start = .delete(:start) || Time.now @stop = .delete(:stop) @times = .delete(:times) @finished = false @on = true @wakeup = [] # threads to wakeup when finished @previous = nil @next = nil @count = 0 end |
Instance Attribute Details
#count ⇒ Object (readonly)
Integer, counting how many times one_done was called.
79 80 81 |
# File 'lib/event.rb', line 79 def count @count end |
#next ⇒ Object (readonly)
Time object containing the time when the event is due next Will be nil if there’s no next event possible to schedule (technically, not due to the event being finished, over stop or over times)
73 74 75 |
# File 'lib/event.rb', line 73 def next @next end |
#previous ⇒ Object (readonly)
Time object containing the time when the event was due the las time
76 77 78 |
# File 'lib/event.rb', line 76 def previous @previous end |
#scheduler ⇒ Object
:nodoc: FIXME, make it foolproof (no change of responsible scheduler)
82 83 84 |
# File 'lib/event.rb', line 82 def scheduler @scheduler end |
#start ⇒ Object (readonly)
Time after which the event will be scheduled
62 63 64 |
# File 'lib/event.rb', line 62 def start @start end |
#stop ⇒ Object (readonly)
Time after which the event won’t be scheduled anymore
65 66 67 |
# File 'lib/event.rb', line 65 def stop @stop end |
#times ⇒ Object (readonly)
Integer or nil, containing how many times the event will be due.
68 69 70 |
# File 'lib/event.rb', line 68 def times @times end |
Class Method Details
.at(*datetimes, &block) ⇒ Object
Creates a Schedule that is invoked at specified datetimes. Postponing an at Schedule will set @next to the first datetime that gives a positive seconds_left.
109 110 111 |
# File 'lib/event.rb', line 109 def at(*datetimes, &block) At.new(datetimes, &block) end |
.every(seconds, options = {}, &block) ⇒ Object
Creates a Schedule which is invoked in an interval, every <seconds> seconds. Postponing an every Schedule will set Schedule#next to Time.now+<seconds>.
89 90 91 |
# File 'lib/event.rb', line 89 def every(seconds, ={}, &block) Every.new(seconds, , &block) end |
.timed(hours = [0], minutes = [0], seconds = [0], options = {}, &block) ⇒ Object
Creates a Schedule which is invoked at specified hours, minutes and seconds of a day. Formats are: “*” Every (hour, minute, second) 4 Same as “0/4” “2/4” Every 4 (hour, minutes, seconds), starting with 2 [1,5] Every specified (hour, minute, second) in the array 0..5 Same as 0..5.to_a Postponing a timed Schedule will set @next to the next hour, minute, second- combination that gives a positive seconds_left.
102 103 104 |
# File 'lib/event.rb', line 102 def timed(hours=[0], minutes=[0], seconds=[0], ={}, &block) Timed.new(hours, minutes, seconds, , &block) end |
Instance Method Details
#<=>(other) ⇒ Object
returns -1, 0 or 1 (smaller, equal to, bigger then other) nil-values for seconds_left are treaded like +INF <=> is overloaded, returning for
-
Event: self.seconds_left <=> other.seconds_left (anything responding to .seconds_left)
-
Time: self.next <=> other (only instances of Time, not Date nor DateTime)
-
Numeric: self.to_f <=> other.to_f (anything responding to .to_f)
240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
# File 'lib/event.rb', line 240 def <=>(other) return @next ? @next <=> other : 1 if other.kind_of?(Time) if other.respond_to?(:seconds_left) me = seconds_left other = other.seconds_left else me = to_f other = other.to_f end return me <=> other if me and other return -1 if me return 1 if other 0 end |
#alter(by_seconds = 0) ⇒ Object
alterates the next-time exactly by “by_seconds”, doesn’t influence anything else.
164 165 166 167 168 |
# File 'lib/event.rb', line 164 def alter(by_seconds=0) @next += by_seconds update_scheduler @next end |
#call(*args) ⇒ Object
Invoke the event
130 131 132 |
# File 'lib/event.rb', line 130 def call(*args) @block.call(*args) end |
#due?(time = nil) ⇒ Boolean
Whether Scheduled event is due now. A finished or off? event is never due?.
210 211 212 |
# File 'lib/event.rb', line 210 def due?(time=nil) @on && !@finished && seconds_left(time) <= 0 end |
#extract_time_range(range, rangeEnd, divisors) ⇒ Object
Normalizes inputs like “*”, “1/12”, 12, [1, 13], (1..5) to an array of all corresponding integers.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
# File 'lib/event.rb', line 275 def extract_time_range(range, rangeEnd, divisors) if range == "*" then (0..rangeEnd).to_a elsif (range.kind_of?(Integer) && divisors.include?(range)) then (0..rangeEnd).stepped(range) elsif (range.kind_of?(String) && !/^\d+\/\d+$/.match(range).nil?) then a,b = *range.match(/(\d+)\/(\d+)/).captures (a.to_i..rangeEnd).stepped(b.to_i) elsif (range.kind_of?(Range) && range.begin >= 0 && range.end <= rangeEnd) return range.to_a elsif (range.kind_of?(Array)) return range else raise ArgumentError, "Invalid range #{range} (#{rangeEnd})" end end |
#finished ⇒ Object
Define the Event as finished and remove it from the scheduler (if scheduled). seconds_left will return nil, <=> will be 1 or 0 (0 for other finished events)
190 191 192 193 194 |
# File 'lib/event.rb', line 190 def finished @finished = true @wakeup.each { |thread| thread.wakeup } nil end |
#finished? ⇒ Boolean
Whether an event has been declared as finished or not. Events that have any kind of limit (:stop, :times) can become automatically finished. Finished events are never due?.
218 219 220 |
# File 'lib/event.rb', line 218 def finished? @finished end |
#join ⇒ Object
Stop current thread until this event is finished.
268 269 270 271 |
# File 'lib/event.rb', line 268 def join @wakeup << Thread.current sleep unless finished? end |
#off ⇒ Object
Switch the Scheduled event off. seconds_left will return nil. See Scheduled#on, Scheduled#on?, Scheduled#off?
182 183 184 185 186 |
# File 'lib/event.rb', line 182 def off @on = false update_scheduler self end |
#off? ⇒ Boolean
Whether an event has been switched off (see Scheduled#off). Off? events are never due?.
229 230 231 |
# File 'lib/event.rb', line 229 def off? !@on end |
#on ⇒ Object
Switch the Scheduled event on. seconds_left will return seconds again. See Scheduled#off, Scheduled#on?, Scheduled#off?
173 174 175 176 177 |
# File 'lib/event.rb', line 173 def on @on = true update_scheduler self end |
#on? ⇒ Boolean
Whether an event has been switched on (default).
223 224 225 |
# File 'lib/event.rb', line 223 def on? @on end |
#one_done(increment = true) ⇒ Object
Increment @count by one and return @next or nil if event is finished
135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/event.rb', line 135 def one_done(increment=true) raise "no next" unless @next raise "Cannot execute deactivated events." unless @on @count += 1 if increment @previous = @next return finished unless @next = calculate_next(@previous) return finished if @times && @count >= @times return finished if @stop && @next > @stop @next end |
#reschedule(by_seconds = 0, postpone_stop = true) ⇒ Object Also known as: postpone
Will reinitalize the Scheduled event with start time beeing the current time. This results in seconds_left beeing the next positive amount (or nil if not postpone_stop and next event would be after @stop) Useful together with Scheduled#off, Scheduled#on
152 153 154 155 156 157 158 159 |
# File 'lib/event.rb', line 152 def reschedule(by_seconds=0, postpone_stop=true) raise "Cannot postpone finished events." if @finished @next = calculate_first(Time.now+by_seconds) finished if !@next || (!postpone_stop && @stop && @next > @stop) update_scheduler @next end |
#seconds_left(time = nil) ⇒ Object
returns seconds left until next Timed returns nil if event is past @stop-datetime returns nil if event has been processed the specified amount of times
199 200 201 |
# File 'lib/event.rb', line 199 def seconds_left(time=nil) (!@finished && @on && @next) && @next - (time||Time.now) end |
#times_left ⇒ Object
returns how many times the event still has to be executed
204 205 206 |
# File 'lib/event.rb', line 204 def times_left @times && @times-@count end |
#to_f ⇒ Object
The left time to next due? as float. IGNORES ON/OFF STATUS, use seconds_left for that.
263 264 265 |
# File 'lib/event.rb', line 263 def to_f seconds_left.to_f end |
#to_i ⇒ Object
The left time to next due? as integer. IGNORES ON/OFF STATUS, use seconds_left for that.
257 258 259 |
# File 'lib/event.rb', line 257 def to_i seconds_left.to_i end |
#update_scheduler ⇒ Object
292 293 294 |
# File 'lib/event.rb', line 292 def update_scheduler @scheduler.reschedule(self) if @scheduler end |