Ver código fonte

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 anos atrás
pai
commit
94cec5e4cd

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

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

+ 10 - 2
app/models/agent.rb

@@ -22,7 +22,7 @@ class Agent < ActiveRecord::Base
 
   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] })]
 
-  attr_accessible :options, :memory, :name, :type, :schedule, :controller_ids, :control_target_ids, :disabled, :source_ids, :scenario_ids, :keep_events_for, :propagate_immediately
+  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
 
   json_serialize :options, :memory
 
@@ -196,6 +196,14 @@ class Agent < ActiveRecord::Base
     update_column :last_error_log_at, nil
   end
 
+  def drop_pending_events
+    false
+  end
+
+  def drop_pending_events=(bool)
+    set_last_checked_event_id if bool
+  end
+
   # Callbacks
 
   def set_default_schedule
@@ -207,7 +215,7 @@ class Agent < ActiveRecord::Base
   end
 
   def set_last_checked_event_id
-    if newest_event_id = Event.order("id desc").limit(1).pluck(:id).first
+    if can_receive_events? && newest_event_id = Event.maximum(:id)
       self.last_checked_event_id = newest_event_id
     end
   end

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

@@ -20,10 +20,12 @@
   </li>
 
   <li>
-    <% if agent.disabled? %>
-      <%= link_to '<i class="glyphicon glyphicon-play"></i> Enable agent'.html_safe, agent_path(agent, :agent => { :disabled => false }, :return => returnTo), :method => :put %>
-    <% else %>
-      <%= link_to '<i class="glyphicon glyphicon-pause"></i> Disable agent'.html_safe, agent_path(agent, :agent => { :disabled => true }, :return => returnTo), :method => :put %>
+    <%= link_to '#', 'data-toggle' => 'modal', 'data-target' => "#confirm-agent#{agent.id}" do %>
+      <% if agent.disabled? %>
+        <i class="glyphicon glyphicon-play"></i> Enable agent
+      <% else %>
+        <i class="glyphicon glyphicon-pause"></i> Disable agent
+      <% end %>
     <% end %>
   </li>
 
@@ -49,3 +51,32 @@
     <%= 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" %>
   </li>
 </ul>
+
+<div id="confirm-agent<%= agent.id %>" class="confirm-agent modal fade" tabindex="-1" role="dialog" aria-labelledby="confirmAgentLabel" aria-hidden="true">
+  <div class="modal-dialog modal-sm">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
+        <h4 class="modal-title">Confirm</h4>
+      </div>
+      <div class="modal-body">
+        <p><% if agent.disabled? %>Enable<% else %>Disable<% end %> &quot;<%= agent.name %>&quot;?</p>
+      </div>
+      <div class="modal-footer">
+        <%= form_for(agent, as: :agent, url: agent_path(agent, return: returnTo), method: 'PUT') do |f| %>
+          <% if agent.disabled && agent.can_receive_events? %>
+            <div class="form-group">
+              <%= f.check_box :drop_pending_events %>
+              <%= f.label :drop_pending_events, 'Drop pending events' %>
+              <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>
+            </div>
+          <% end %>
+          <%= f.hidden_field :disabled, value: (!agent.disabled).to_s %>
+          <%= f.button 'No', class: 'btn btn-default', 'data-dismiss' => 'modal' %>
+          <%= f.submit 'Yes', class: 'btn btn-primary' %>
+        <% end %>
+      </div>
+    </div>
+  </div>
+</div>
+

+ 12 - 0
spec/controllers/agents_controller_spec.rb

@@ -251,6 +251,18 @@ describe AgentsController do
         response.should redirect_to(agents_path)
       end
     end
+
+    it "updates last_checked_event_id when drop_pending_events is given" do
+      sign_in users(:bob)
+      agent = agents(:bob_website_agent)
+      agent.disabled = true
+      agent.last_checked_event_id = nil
+      agent.save!
+      post :update, id: agents(:bob_website_agent).to_param, agent: { disabled: 'false', drop_pending_events: 'true' }
+      agent.reload
+      agent.disabled.should == false
+      agent.last_checked_event_id.should == Event.maximum(:id)
+    end
   end
 
   describe "PUT leave_scenario" do

+ 53 - 0
spec/models/agent_spec.rb

@@ -757,6 +757,59 @@ describe Agent do
       end
     end
   end
+
+  describe '.last_checked_event_id' do
+    it "should be updated by setting drop_pending_events to true" do
+      agent = agents(:bob_rain_notifier_agent)
+      agent.last_checked_event_id = nil
+      agent.save!
+      agent.update!(drop_pending_events: true)
+      agent.reload.last_checked_event_id.should == Event.maximum(:id)
+    end
+
+    it "should not affect a virtual attribute drop_pending_events" do
+      agent = agents(:bob_rain_notifier_agent)
+      agent.update!(drop_pending_events: true)
+      agent.reload.drop_pending_events.should == false
+    end
+  end
+
+  describe ".drop_pending_events" do
+    before do
+      stub_request(:any, /wunderground/).to_return(body: File.read(Rails.root.join("spec/data_fixtures/weather.json")), status: 200)
+      stub.any_instance_of(Agents::WeatherAgent).is_tomorrow?(anything) { true }
+    end
+
+    it "should drop pending events while the agent was disabled when set to true" do
+      agent1 = agents(:bob_weather_agent)
+      agent2 = agents(:bob_rain_notifier_agent)
+
+      -> {
+        -> {
+          Agent.async_check(agent1.id)
+          Agent.receive!
+        }.should change { agent1.events.count }.by(1)
+      }.should change { agent2.events.count }.by(1)
+
+      agent2.disabled = true
+      agent2.save!
+
+      -> {
+        -> {
+          Agent.async_check(agent1.id)
+          Agent.receive!
+        }.should change { agent1.events.count }.by(1)
+      }.should_not change { agent2.events.count }
+
+      agent2.disabled = false
+      agent2.drop_pending_events = true
+      agent2.save!
+
+      -> {
+        Agent.receive!
+      }.should_not change { agent2.events.count }
+    end
+  end
 end
 
 describe AgentDrop do