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.
118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/event.rb', line 118 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.
82 83 84 |
# File 'lib/event.rb', line 82 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)
76 77 78 |
# File 'lib/event.rb', line 76 def next @next end |
#previous ⇒ Object (readonly)
Time object containing the time when the event was due the las time
79 80 81 |
# File 'lib/event.rb', line 79 def previous @previous end |
#scheduler ⇒ Object
:nodoc: FIXME, make it foolproof (no change of responsible scheduler)
85 86 87 |
# File 'lib/event.rb', line 85 def scheduler @scheduler end |
#start ⇒ Object (readonly)
Time after which the event will be scheduled
65 66 67 |
# File 'lib/event.rb', line 65 def start @start end |
#stop ⇒ Object (readonly)
Time after which the event won’t be scheduled anymore
68 69 70 |
# File 'lib/event.rb', line 68 def stop @stop end |
#times ⇒ Object (readonly)
Integer or nil, containing how many times the event will be due.
71 72 73 |
# File 'lib/event.rb', line 71 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.
112 113 114 |
# File 'lib/event.rb', line 112 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>.
92 93 94 |
# File 'lib/event.rb', line 92 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.
105 106 107 |
# File 'lib/event.rb', line 105 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)
243 244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/event.rb', line 243 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.
167 168 169 170 171 |
# File 'lib/event.rb', line 167 def alter(by_seconds=0) @next += by_seconds update_scheduler @next end |
#call(*args) ⇒ Object
Invoke the event
133 134 135 |
# File 'lib/event.rb', line 133 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?.
213 214 215 |
# File 'lib/event.rb', line 213 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.
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/event.rb', line 278 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)
193 194 195 196 197 |
# File 'lib/event.rb', line 193 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?.
221 222 223 |
# File 'lib/event.rb', line 221 def finished? @finished end |
#join ⇒ Object
Stop current thread until this event is finished.
271 272 273 274 |
# File 'lib/event.rb', line 271 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?
185 186 187 188 189 |
# File 'lib/event.rb', line 185 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?.
232 233 234 |
# File 'lib/event.rb', line 232 def off? !@on end |
#on ⇒ Object
Switch the Scheduled event on. seconds_left will return seconds again. See Scheduled#off, Scheduled#on?, Scheduled#off?
176 177 178 179 180 |
# File 'lib/event.rb', line 176 def on @on = true update_scheduler self end |
#on? ⇒ Boolean
Whether an event has been switched on (default).
226 227 228 |
# File 'lib/event.rb', line 226 def on? @on end |
#one_done(increment = true) ⇒ Object
Increment @count by one and return @next or nil if event is finished
138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/event.rb', line 138 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
155 156 157 158 159 160 161 162 |
# File 'lib/event.rb', line 155 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
202 203 204 |
# File 'lib/event.rb', line 202 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
207 208 209 |
# File 'lib/event.rb', line 207 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.
266 267 268 |
# File 'lib/event.rb', line 266 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.
260 261 262 |
# File 'lib/event.rb', line 260 def to_i seconds_left.to_i end |
#update_scheduler ⇒ Object
295 296 297 |
# File 'lib/event.rb', line 295 def update_scheduler @scheduler.reschedule(self) if @scheduler end |