1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
# encoding: UTF-8
require 'mauve/datamapper'
require 'log4r'
module Mauve
class AlertChanged
include DataMapper::Resource
# so .first always returns the most recent update
default_scope(:default).update(:order => [:at.desc, :id.desc])
property :id, Serial
property :alert_id, Integer, :required => true
property :person, String, :required => true
property :at, DateTime, :required => true
property :was_relevant, Boolean, :required => true, :default => true
property :level, String, :required => true
property :update_type, String, :required => true
property :remind_at, DateTime
property :updated_at, DateTime
def to_s
"#<AlertChanged:#{id} of #{alert_id} for #{person} update_type #{update_type}>"
end
belongs_to :alert
# There is a bug there. You could have two reminders for the same
# person if that person has two different notify clauses.
#
# See the test cases test_Bug_reminders_get_trashed() in ./test/
after :create do
old_changed = AlertChanged.first(
:alert_id => alert_id,
:person => person,
:id.not => id,
:remind_at.not => nil
)
if old_changed
if !old_changed.update(:remind_at => nil)
logger.error "Couldn't save #{old_changed}, will get duplicate reminders"
end
end
end
def was_relevant=(value)
attribute_set(:was_relevant, value)
end
def logger
Log4r::Logger.new self.class.to_s
end
## Checks to see if a raise was send to the person.
#
# @TODO: Recurence is broken in ruby, change this so that it does not
# use it.
#
# @author Matthew Bloch
# @return [Boolean] true if it was relevant, false otherwise.
def was_relevant_when_raised?
if :acknowledged == update_type.to_sym and true == was_relevant
return true
end
return was_relevant if update_type.to_sym == :raised
previous = AlertChanged.first(:id.lt => id,
:alert_id => alert_id,
:person => person)
if previous
previous.was_relevant_when_raised?
else
# a bug, but hardly inconceivable :)
logger.warn("Could not see that #{alert} was raised with #{person} "+
"but further updates exist (e.g. #{self}) "+
"- you may see spurious notifications as a result")
true
end
end
# Sends a reminder about this alert state change, or forget about it if
# the alert has been acknowledged
#
def remind
unless alert.is_a?(Alert)
logger.debug "#{self.inspect} lost alert #{alert_id}. Killing self."
destroy!
return false
end
logger.debug "Reminding someone about #{self.inspect}"
alert_group = AlertGroup.matches(alert)[0]
if !alert_group || alert.acknowledged?
logger.debug((alert_group ?
"Alert already acknowledged" :
"No alert group matches any more"
) + ", no reminder due"
)
self.remind_at = nil
save
else
saved = false
unless alert_group.notifications.nil?
alert_group.notifications.each do |notification|
notification.people.each do |person|
# Not interested in nil people.
next if person.nil?
if person.username == self.person
person.remind(alert, level)
self.remind_at = notification.remind_at_next(alert)
save
saved = true
end
end
end
end
if !saved
logger.warn("#{self.inspect} did not match any people, maybe configuration has changed but I'm going to delete this and not try to remind anyone again")
destroy!
end
end
end
def due_at # mimic interface from Alert
remind_at ? remind_at.to_time : nil
end
def poll # mimic interface from Alert
remind if remind_at.to_time <= MauveTime.now
end
class << self
def next_reminder
first(:remind_at.not => nil, :order => [:remind_at])
end
def find_next_with_event # mimic interface from Alert
next_reminder
end
def all_overdue(at = MauveTime.now)
all(:remind_at.not => nil, :remind_at.lt => at, :order => [:remind_at]).to_a
end
end
end
end
|