diff options
Diffstat (limited to 'lib/mauve/person.rb')
-rw-r--r-- | lib/mauve/person.rb | 123 |
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 # |