Merge pull request #511 from knu/agent-drop_pending_events

Give user an option to drop pending events when enabling an agent.

Akinori MUSHA 10 gadi atpakaļ
vecāks
revīzija
94cec5e4cd

+ 4 - 0
app/assets/stylesheets/application.css.scss.erb

@@ -228,3 +228,7 @@ h2 .scenario, a span.label.scenario {
228 228
     display: none;
229 229
   }
230 230
 }
231
+
232
+.confirm-agent .popover {
233
+  width: 200px;
234
+}

+ 10 - 2
app/models/agent.rb

@@ -22,7 +22,7 @@ class Agent < ActiveRecord::Base
22 22
 
23 23
   EVENT_RETENTION_SCHEDULES = [["Forever", 0], ["1 day", 1], *([2, 3, 4, 5, 7, 14, 21, 30, 45, 90, 180, 365].map {|n| ["#{n} days", n] })]
24 24
 
25
-  attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately
25
+  attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately, :drop_pending_events
26 26
 
27 27
   json_serialize :options, :memory
28 28
 
@@ -196,6 +196,14 @@ class Agent < ActiveRecord::Base
196 196
     update_column :last_error_log_at, nil
197 197
   end
198 198
 
199
+  def drop_pending_events
200
+    false
201
+  end
202
+
203
+  def drop_pending_events=(bool)
204
+    set_last_checked_event_id if bool
205
+  end
206
+
199 207
   # Callbacks
200 208
 
201 209
   def set_default_schedule
@@ -207,7 +215,7 @@ class Agent < ActiveRecord::Base
207 215
   end
208 216
 
209 217
   def set_last_checked_event_id
210
-    if newest_event_id = Event.order("id desc").limit(1).pluck(:id).first
218
+    if can_receive_events? && newest_event_id = Event.maximum(:id)
211 219
       self.last_checked_event_id = newest_event_id
212 220
     end
213 221
   end

+ 35 - 4
app/views/agents/_action_menu.html.erb

@@ -20,10 +20,12 @@
20 20
   </li>
21 21
 
22 22
   <li>
23
-    <% if agent.disabled? %>
24
-      <%= link_to '<i class="glyphicon glyphicon-play"></i> Enable agent'.html_safe, agent_path(agent, :agent => { :disabled => false }, :return => returnTo), :method => :put %>
25
-    <% else %>
26
-      <%= link_to '<i class="glyphicon glyphicon-pause"></i> Disable agent'.html_safe, agent_path(agent, :agent => { :disabled => true }, :return => returnTo), :method => :put %>
23
+    <%= link_to '#', 'data-toggle' => 'modal', 'data-target' => "#confirm-agent#{agent.id}" do %>
24
+      <% if agent.disabled? %>
25
+        <i class="glyphicon glyphicon-play"></i> Enable agent
26
+      <% else %>
27
+        <i class="glyphicon glyphicon-pause"></i> Disable agent
28
+      <% end %>
27 29
     <% end %>
28 30
   </li>
29 31
 
@@ -49,3 +51,32 @@
49 51
     <%= link_to '<span class="color-danger glyphicon glyphicon-remove"></span> Delete agent'.html_safe, agent_path(agent, :return => returnTo), method: :delete, data: { confirm: 'Are you sure that you want to permanently delete this Agent?' }, :tabindex => "-1" %>
50 52
   </li>
51 53
 </ul>
54
+
55
+<div id="confirm-agent<%= agent.id %>" class="confirm-agent modal fade" tabindex="-1" role="dialog" aria-labelledby="confirmAgentLabel" aria-hidden="true">
56
+  <div class="modal-dialog modal-sm">
57
+    <div class="modal-content">
58
+      <div class="modal-header">
59
+        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
60
+        <h4 class="modal-title">Confirm</h4>
61
+      </div>
62
+      <div class="modal-body">
63
+        <p><% if agent.disabled? %>Enable<% else %>Disable<% end %> &quot;<%= agent.name %>&quot;?</p>
64
+      </div>
65
+      <div class="modal-footer">
66
+        <%= form_for(agent, as: :agent, url: agent_path(agent, return: returnTo), method: 'PUT') do |f| %>
67
+          <% if agent.disabled && agent.can_receive_events? %>
68
+            <div class="form-group">
69
+              <%= f.check_box :drop_pending_events %>
70
+              <%= f.label :drop_pending_events, 'Drop pending events' %>
71
+              <span class="glyphicon glyphicon-question-sign hover-help" data-content="As soon as you enable this agent, it starts to receive pending events that have not been processed while it was disabled.  To prevent that from happening, you can check this option."></span>
72
+            </div>
73
+          <% end %>
74
+          <%= f.hidden_field :disabled, value: (!agent.disabled).to_s %>
75
+          <%= f.button 'No', class: 'btn btn-default', 'data-dismiss' => 'modal' %>
76
+          <%= f.submit 'Yes', class: 'btn btn-primary' %>
77
+        <% end %>
78
+      </div>
79
+    </div>
80
+  </div>
81
+</div>
82
+

+ 12 - 0
spec/controllers/agents_controller_spec.rb

@@ -251,6 +251,18 @@ describe AgentsController do
251 251
         response.should redirect_to(agents_path)
252 252
       end
253 253
     end
254
+
255
+    it "updates last_checked_event_id when drop_pending_events is given" do
256
+      sign_in users(:bob)
257
+      agent = agents(:bob_website_agent)
258
+      agent.disabled = true
259
+      agent.last_checked_event_id = nil
260
+      agent.save!
261
+      post :update, id: agents(:bob_website_agent).to_param, agent: { disabled: 'false', drop_pending_events: 'true' }
262
+      agent.reload
263
+      agent.disabled.should == false
264
+      agent.last_checked_event_id.should == Event.maximum(:id)
265
+    end
254 266
   end
255 267
 
256 268
   describe "PUT leave_scenario" do

+ 53 - 0
spec/models/agent_spec.rb

@@ -757,6 +757,59 @@ describe Agent do
757 757
       end
758 758
     end
759 759
   end
760
+
761
+  describe '.last_checked_event_id' do
762
+    it "should be updated by setting drop_pending_events to true" do
763
+      agent = agents(:bob_rain_notifier_agent)
764
+      agent.last_checked_event_id = nil
765
+      agent.save!
766
+      agent.update!(drop_pending_events: true)
767
+      agent.reload.last_checked_event_id.should == Event.maximum(:id)
768
+    end
769
+
770
+    it "should not affect a virtual attribute drop_pending_events" do
771
+      agent = agents(:bob_rain_notifier_agent)
772
+      agent.update!(drop_pending_events: true)
773
+      agent.reload.drop_pending_events.should == false
774
+    end
775
+  end
776
+
777
+  describe ".drop_pending_events" do
778
+    before do
779
+      stub_request(:any, /wunderground/).to_return(body: File.read(Rails.root.join("spec/data_fixtures/weather.json")), status: 200)
780
+      stub.any_instance_of(Agents::WeatherAgent).is_tomorrow?(anything) { true }
781
+    end
782
+
783
+    it "should drop pending events while the agent was disabled when set to true" do
784
+      agent1 = agents(:bob_weather_agent)
785
+      agent2 = agents(:bob_rain_notifier_agent)
786
+
787
+      -> {
788
+        -> {
789
+          Agent.async_check(agent1.id)
790
+          Agent.receive!
791
+        }.should change { agent1.events.count }.by(1)
792
+      }.should change { agent2.events.count }.by(1)
793
+
794
+      agent2.disabled = true
795
+      agent2.save!
796
+
797
+      -> {
798
+        -> {
799
+          Agent.async_check(agent1.id)
800
+          Agent.receive!
801
+        }.should change { agent1.events.count }.by(1)
802
+      }.should_not change { agent2.events.count }
803
+
804
+      agent2.disabled = false
805
+      agent2.drop_pending_events = true
806
+      agent2.save!
807
+
808
+      -> {
809
+        Agent.receive!
810
+      }.should_not change { agent2.events.count }
811
+    end
812
+  end
760 813
 end
761 814
 
762 815
 describe AgentDrop do