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.



118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/event.rb', line 118

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.



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

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)



76
77
78
# File 'lib/event.rb', line 76

def next
  @next
end

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

#schedulerObject

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



85
86
87
# File 'lib/event.rb', line 85

def scheduler
  @scheduler
end

#startObject (readonly)

Time after which the event will be scheduled



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

def start
  @start
end

#stopObject (readonly)

Time after which the event won’t be scheduled anymore



68
69
70
# File 'lib/event.rb', line 68

def stop
  @stop
end

#timesObject (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, 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.



105
106
107
# File 'lib/event.rb', line 105

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)



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

Returns:

  • (Boolean)


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

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



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

Returns:

  • (Boolean)


221
222
223
# File 'lib/event.rb', line 221

def finished?
	@finished
end

#joinObject

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

#offObject

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

Returns:

  • (Boolean)


232
233
234
# File 'lib/event.rb', line 232

def off?
	!@on
end

#onObject

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

Returns:

  • (Boolean)


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_leftObject

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_fObject

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_iObject

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_schedulerObject



295
296
297
# File 'lib/event.rb', line 295

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