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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
# encoding: UTF-8
require 'mauve/datamapper'
require 'log4r'
module Mauve
#
# Class to record changes to alerts. Also responsible for keeping records for reminders.
#
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, EpochTime, :required => true
property :was_relevant, Boolean, :required => true, :default => true
property :level, String, :required => true
property :update_type, String, :required => true
property :remind_at, EpochTime, :required => false
belongs_to :alert
before :valid?, :do_set_timestamps
protected
def do_set_timestamps(context = :default)
self.at = Time.now if self.dirty?
end
public
# @return [String]
def to_s
"#<AlertChanged #{id}: alert_id #{alert_id}, for #{person}, update_type #{update_type}>"
end
# @deprecated I don't think was_relevant is used any more.
#
def was_relevant=(value)
attribute_set(:was_relevant, value)
end
# The time this object was last updated
#
# @return [Time]
def updated_at
self.at
end
# Set the time this object was last updated
#
# @param [Time] t
# @return [Time]
def updated_at=(t)
self.at = t
end
# @return [Log4r::Logger]
def logger
Log4r::Logger.new self.class.to_s
end
# Sends a reminder about this alert state change, or forget about it if
# the alert has been acknowledged
#
# @return [Boolean] indicating successful update of the AlertChanged object
def remind
unless alert.is_a?(Alert)
logger.info "#{self.inspect} lost alert #{alert_id}. Killing self."
destroy
return false
end
if !alert_group
logger.info("No alert group matches any more. Clearing reminder for #{self.alert}.")
self.remind_at = nil
return save
end
if alert.acknowledged? or alert.cleared?
logger.info("Alert already acknowledged/cleared. Clearing reminder due for #{self.alert}.")
self.remind_at = nil
return save
end
#
# Postpone reminders from previous runs, if needed.
#
if Server.instance.in_initial_sleep? and
self.at < Server.instance.started_at
self.remind_at = Server.instance.started_at + Server.instance.initial_sleep
logger.info("Postponing reminder for #{self.alert} until #{self.remind_at} since this reminder was updated in a prior run of Mauve.")
return save
end
#
# Bail out if notifications for this alert have been suppressed.
#
if alert.suppressed?
#
# Skip reminders if the alert is suppressed.
#
logger.info("Notifications suppressed until #{alert.suppress_until} for #{alert.inspect}")
else
#
# Push this notifitcation onto the queue.
#
Server.notification_push([alert, self.remind_at])
end
#
# Need to make sure this reminder is cleared.
#
self.remind_at = nil
#
# Now save.
#
return self.save
end
# The time this AlertChanged should next be polled at, or nil. Mimics
# interaface from Alert.
#
# @return [Time, NilClass]
def due_at
remind_at ? remind_at : nil
end
# Sends a reminder, if needed. Mimics interaface from Alert.
#
# @return [Boolean] showing polling was successful
def poll # mimic interface from Alert
logger.debug("Polling #{self.to_s}")
if remind_at.is_a?(Time) and remind_at <= Time.now
remind
else
true
end
end
# The AlertGroup for this object
#
# @return [Mauve::AlertGroup]
def alert_group
alert.alert_group
end
class << self
# Finds the next reminder due, or nil if nothing due.
#
# @return [Mauve::AlertChanged, NilClass]
def next_reminder
first(:remind_at.not => nil, :order => [:remind_at])
end
# Finds the next event due. Mimics interface from Alert.
#
# @return [Mauve::AlertChanged, NilClass]
def find_next_with_event
next_reminder
end
# @deprecated I don't think this is used any more.
#
# @return [Array]
def all_overdue(at = Time.now)
all(:remind_at.not => nil, :remind_at.lt => at, :order => [:remind_at]).to_a
end
end
end
end
|