aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/mauve/alert_group.rb41
-rw-r--r--lib/mauve/configuration_builders/alert_group.rb6
-rw-r--r--lib/mauve/notification.rb34
-rw-r--r--test/tc_mauve_notification.rb51
4 files changed, 112 insertions, 20 deletions
diff --git a/lib/mauve/alert_group.rb b/lib/mauve/alert_group.rb
index aa47ef6..31d9cc8 100644
--- a/lib/mauve/alert_group.rb
+++ b/lib/mauve/alert_group.rb
@@ -153,16 +153,39 @@ module Mauve
return false
end
+ during_runners = []
+
#
# This is where we set the reminder -- i.e. on a per-alert-group basis.
- #
- remind_at = notifications.inject(nil) do |reminder_time, notification|
- this_time = notification.remind_at_next(alert, at)
- if reminder_time.nil? or (!this_time.nil? and reminder_time > this_time)
- this_time
- else
- reminder_time
- end
+
+ remind_at = nil
+ notifications.each do |notification|
+ #
+ # Create a new during_runner for this notification clause, and keep it
+ # handy.
+ #
+ during_runner = DuringRunner.new(at, alert, &notification.during)
+ during_runners << during_runner
+
+ #
+ # Work out the next reminder time
+ #
+ this_remind_at = notification.remind_at_next(alert, during_runner)
+
+ #
+ # Skip this one if no reminder time can be found
+ #
+ next if this_remind_at.nil?
+
+ #
+ # Set the next reminder time if we've not had one already.
+ #
+ remind_at = this_remind_at if remind_at.nil?
+
+ #
+ # We need the next soonest reminder time.
+ #
+ remind_at = this_remind_at if remind_at > this_remind_at
end
#
@@ -186,7 +209,7 @@ module Mauve
#
sent_to = []
notifications.each do |notification|
- sent_to << notification.notify(alert, sent_to, at)
+ sent_to << notification.notify(alert, sent_to, during_runners.shift)
end
return (sent_to.length > 0)
diff --git a/lib/mauve/configuration_builders/alert_group.rb b/lib/mauve/configuration_builders/alert_group.rb
index c652de8..56c446d 100644
--- a/lib/mauve/configuration_builders/alert_group.rb
+++ b/lib/mauve/configuration_builders/alert_group.rb
@@ -20,15 +20,15 @@ module Mauve
# @return [Mauve::Notification] New notification instance.
def builder_setup(*who)
who = who.map do |username|
- #raise BuildException.new("You haven't declared who #{username} is") unless
- # @context.people[username]
- #@context.people[username]
if @context.people[username]
@context.people[username]
+
elsif @context.people_lists[username]
@context.people_lists[username]
+
else
raise ArgumentError.new("You have not declared who #{username} is")
+
end
end
@result = Mauve::Notification.new(who, @context.last_alert_group.level)
diff --git a/lib/mauve/notification.rb b/lib/mauve/notification.rb
index a9795f3..522f9fa 100644
--- a/lib/mauve/notification.rb
+++ b/lib/mauve/notification.rb
@@ -42,6 +42,7 @@ module Mauve
@alert = alert
@during = during || Proc.new { true }
@logger = Log4r::Logger.new "Mauve::DuringRunner"
+ @now_cache = Hash.new
end
# This evaluates the +during+ block, returning the result.
@@ -49,8 +50,21 @@ module Mauve
# @param [Time] t Set the time at which to evaluate the +during+ block.
# @return [Boolean]
def now?(t=@time)
+ #
+ # Use the cache if we've already worked out what happens at time t.
+ #
+ return @now_cache[t] if @now_cache.has_key?(t)
+
+ #
+ # Store the test time in an instance variable so the test knows what time
+ # we're testing against.
+ #
@test_time = t
- instance_eval(&@during) ? true : false
+
+ #
+ # Store the answer in our cache and return.
+ #
+ @now_cache[t] = (instance_eval(&@during) ? true : false)
end
# This finds the next occurance of the +during+ block evaluating to true.
@@ -195,15 +209,18 @@ module Mauve
# @param [Array] already_sent_to A list of people that have already received this alert.
#
# @return [Array] The list of people that have received this alert.
- def notify(alert, already_sent_to = [], at=Time.now)
+ def notify(alert, already_sent_to = [], during_runner = nil)
if people.nil? or people.empty?
logger.warn "No people found in for notification #{list}"
return
end
+ # Set up a during_runner
+ during_runner ||= DuringRunner.new(Time.now, self.alert, &self.during)
+
# Should we notify at all?
- return already_sent_to unless DuringRunner.new(at, alert, &during).now?
+ return already_sent_to unless during_runner.now?
people.collect do |person|
case person
@@ -236,15 +253,16 @@ module Mauve
# @param [Mauve::Alert] alert The alert in question
# @return [Time or nil] The time a reminder should get sent, or nil if it
# should never get sent again.
- def remind_at_next(alert, at = Time.now)
+ def remind_at_next(alert, during_runner = nil)
return nil unless alert.raised?
- dr = DuringRunner.new(at, alert, &during)
+ # Set up a during_runner
+ during_runner ||= DuringRunner.new(Time.now, self.alert, &self.during)
- if dr.now?
- return dr.find_next(every)
+ if during_runner.now?
+ return during_runner.find_next(every)
else
- return dr.find_next()
+ return during_runner.find_next()
end
end
diff --git a/test/tc_mauve_notification.rb b/test/tc_mauve_notification.rb
index 0b3bc04..ec5eaf6 100644
--- a/test/tc_mauve_notification.rb
+++ b/test/tc_mauve_notification.rb
@@ -315,4 +315,55 @@ EOF
end
+ #
+ # Test to make sure that if a bondary is crossed, then the during clauses all
+ # work.
+ #
+ def test_no_race_conditions_in_during
+
+ config=<<EOF
+person ("test1") {
+ all { true }
+}
+
+person ("test2") {
+ all { true }
+}
+
+alert_group("default") {
+ level URGENT
+ notify("test1") {
+ every 0
+ during { sleep 1 ; hours_in_day 1..7 }
+ }
+
+ notify("test2") {
+ every 0
+ during { hours_in_day 8..10 }
+ }
+
+}
+EOF
+
+ #
+ # Wind forward until 7:59:59am
+ #
+ Timecop.travel(Time.now + 7.hours + 59.minutes + 59.seconds)
+ Configuration.current = ConfigurationBuilder.parse(config)
+ Server.instance.setup
+ alert = Alert.new(
+ :alert_id => "test",
+ :source => "test",
+ :subject => "test"
+ )
+ alert.raise!
+
+ a = AlertChanged.first
+ assert_equal("urgent", a.level, "Level is wrong for #{a.person}")
+ assert_equal("raised", a.update_type, "Update type is wrong for #{a.person}")
+
+ assert_equal(1, Server.instance.notification_buffer.size, "Wrong number of notifications sent")
+ end
+
+
end