aboutsummaryrefslogtreecommitdiff
path: root/lib/mauve/person.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mauve/person.rb')
-rw-r--r--lib/mauve/person.rb123
1 files changed, 80 insertions, 43 deletions
diff --git a/lib/mauve/person.rb b/lib/mauve/person.rb
index 979c0ab..1158cbf 100644
--- a/lib/mauve/person.rb
+++ b/lib/mauve/person.rb
@@ -6,13 +6,12 @@ module Mauve
class Person
attr_reader :username, :password, :urgent, :normal, :low, :email, :xmpp, :sms
- attr_reader :notification_thresholds, :last_pop3_login, :suppressed, :notifications
+ attr_reader :last_pop3_login, :suppressed, :notifications
attr_reader :notify_when_off_sick, :notify_when_on_holiday
# Set up a new Person
#
def initialize(username)
- @notification_thresholds = nil
@suppressed = false
#
# TODO fix up web login so pop3 can be used as a proxy.
@@ -107,34 +106,85 @@ module Mauve
# Works out if a notification should be suppressed. If no parameters are supplied, it will
#
+ # @param [Symbol] Level of notification that is being tested
# @param [Time] Theoretical time of notification
# @param [Time] Current time.
# @return [Boolean] If suppression is needed.
- def should_suppress?(with_notification_at = nil, now = Time.now)
+ def should_suppress?(level, with_notification_at = nil, now = Time.now)
- return self.notification_thresholds.any? do |period, previous_alert_times|
+ self.suppress_notifications_after.any? do |period, number|
#
- # This is going to work out if we would be suppressed if
- if with_notification_at.nil?
- first = previous_alert_times.first
- last = previous_alert_times.last
+ # When testing if the next alert will suppress, we know that if only
+ # one alert is needed to suppress, then this function should always
+ # return true.
+ #
+ return true if with_notification_at and number <= 1
+
+ #
+ # Here are the previous notifications set to this person in the last period.
+ #
+ previous_notifications = History.all(
+ :user => self.username, :type => "notification",
+ :created_at.gte => now - period, :created_at.lte => now,
+ :event.like => '% succeeded',
+ :order => :created_at.desc)
+
+ #
+ # Defintely not suppressed if no notifications have been found.
+ #
+ return false if previous_notifications.count == 0
+
+ #
+ # If we're suppressed already, we need to check the time of the last alert sent
+ #
+ if @suppressed
+
+ if with_notification_at.is_a?(Time)
+ latest = with_notification_at
+ else
+ latest = previous_notifications.first.created_at
+ end
+
+ #
+ # We should not suppress this alert if the last one was sent ages ago
+ #
+ if (now - latest) >= period
+ return false
+ end
+
else
- first = previous_alert_times[1]
- last = with_notification_at
+ #
+ # We do not suppress if we can't find a sufficient number of previous alerts
+ #
+ if previous_notifications.count < (with_notification_at.nil? ? number : number - 1)
+ return false
+ end
+
end
-
- (first.is_a?(Time) and (now - first) < period) or
- (last.is_a?(Time) and @suppressed and (now - last) < period)
+
+ #
+ # If we're at the lowest level, return true now.
+ #
+ return true if !AlertGroup::LEVELS.include?(level) or AlertGroup::LEVELS.index(level) == 0
+
+ #
+ # Suppress this notification if all the last N of the preceeding
+ # notifications were of a equal or higher level.
+ #
+ return previous_notifications.first(number).alerts.to_a.all? do |a|
+ AlertGroup::LEVELS.index(a.level) >= AlertGroup::LEVELS.index(level)
+ end
+
end
end
- # The notification thresholds for this user
#
- # @return [Hash]
- def notification_thresholds
- @notification_thresholds ||= { }
+ #
+ #
+ def suppress_notifications_after
+ @suppress_notifications_after ||= { }
end
-
+
# This class implements an instance_eval context to execute the blocks
# for running a notification block for each person.
#
@@ -203,10 +253,8 @@ module Mauve
#
# Log the result
- note = "#{@alert.update_type.capitalize} #{name} notification to #{@person.username} (#{destination}) " + (res ? "succeeded" : "failed" )
- logger.info note+" about #{@alert}."
- h = History.new(:alerts => [@alert], :type => "notification", :event => note, :user => @person.username)
- h.save
+ #
+ logger.info "#{@alert.update_type.capitalize} #{name} notification to #{@person.username} (#{destination}) " + (res ? "succeeded" : "failed" ) +" about #{@alert}."
return res
end
@@ -222,17 +270,17 @@ module Mauve
def send_alert(level, alert, now=Time.now)
was_suppressed = @suppressed
- @suppressed = self.should_suppress?
- will_suppress = self.should_suppress?(now)
+ @suppressed = self.should_suppress?(level)
+ will_suppress = self.should_suppress?(level, now)
logger.info "Starting to send notifications again for #{username}." if was_suppressed and not @suppressed
-
+
#
# We only suppress notifications if we were suppressed before we started,
# and are still suppressed.
#
if @suppressed or self.is_on_holiday?(now) or self.is_off_sick?(now)
- note = "#{alert.update_type.capitalize} notification to #{self.username} suppressed"
+ note = "#{alert.update_type.capitalize} #{level} notification to #{self.username} suppressed"
logger.info note + " about #{alert}."
History.create(:alerts => [alert], :type => "notification", :event => note, :user => self.username)
return true
@@ -253,24 +301,13 @@ module Mauve
:was_suppressed => was_suppressed, }
).instance_eval(&__send__(level))
end
+
+ res = [result].flatten.any?
+
+ note = "#{alert.update_type.capitalize} #{level} notification to #{self.username} " + (res ? "succeeded" : "failed" )
+ History.create(:alerts => [alert], :type => "notification", :event => note, :user => self.username)
- if [result].flatten.any?
- #
- # Remember that we've sent an alert
- #
- self.notification_thresholds.each do |period, previous_alert_times|
- #
- # Hmm.. not sure how to make this thread-safe.
- #
- self.notification_thresholds[period].push now
- self.notification_thresholds[period].shift
- end
-
-
- return true
- end
-
- return false
+ return res
end
#