Class: Event

Inherits:
Object
  • Object
show all
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])

Direct Known Subclasses

At, Every, Timed

Defined Under Namespace

Classes: At, Every, Timed

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

Class Method Summary collapse

Instance Method Summary collapse

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(options={}, &block) # :nodoc:
	@block    = block
	@start    = options.delete(:start) || Time.now
	@stop     = options.delete(:stop)
	@times    = options.delete(:times)
	@finished = false
	@on       = true
	@wakeup   = [] # threads to wakeup when finished

	@previous = nil
	@next     = nil
	@count    = 0
end

Instance Attribute Details

#countObject (readonly)

Integer, counting how many times one_done was called.



79
80
81
# File 'lib/event.rb', line 79

def count
  @count
end

#nextObject (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

#previousObject (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

#schedulerObject

:nodoc: FIXME, make it foolproof (no change of responsible scheduler)



82
83
84
# File 'lib/event.rb', line 82

def scheduler
  @scheduler
end

#startObject (readonly)

Time after which the event will be scheduled



62
63
64
# File 'lib/event.rb', line 62

def start
  @start
end

#stopObject (readonly)

Time after which the event won’t be scheduled anymore



65
66
67
# File 'lib/event.rb', line 65

def stop
  @stop
end

#timesObject (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, options={}, &block)
	Every.new(seconds, options, &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], options={}, &block)
	Timed.new(hours, minutes, seconds, options, &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?.

Returns:

  • (Boolean)


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

#finishedObject

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?.

Returns:

  • (Boolean)


218
219
220
# File 'lib/event.rb', line 218

def finished?
	@finished
end

#joinObject

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

#offObject

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?.

Returns:

  • (Boolean)


229
230
231
# File 'lib/event.rb', line 229

def off?
	!@on
end

#onObject

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).

Returns:

  • (Boolean)


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_leftObject

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_fObject

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_iObject

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_schedulerObject



292
293
294
# File 'lib/event.rb', line 292

def update_scheduler
	@scheduler.reschedule(self) if @scheduler
end