Skip to content

Commit 5895da1

Browse files
author
Vidas P
committed
Add workflow reset functionality
Delete all workflow messages, logs and optionally - agent memory.
1 parent 76fe203 commit 5895da1

File tree

11 files changed

+174
-1
lines changed

11 files changed

+174
-1
lines changed

app/controllers/workflows_controller.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ def enable_or_disable_all_agents
104104
end
105105
end
106106

107+
def reset
108+
workflow = current_user.workflows.find(params[:id])
109+
110+
erase_memory = params[:erase_memory]
111+
112+
workflow.reset(erase_memory: erase_memory)
113+
114+
respond_to do |format|
115+
format.html { redirect_to workflow, notice: 'The workflow has been reset.' }
116+
format.json { head :no_content }
117+
end
118+
end
119+
107120
def destroy
108121
@workflow = current_user.workflows.find(params[:id])
109122
@workflow.destroy_with_mode(params[:mode])

app/models/workflow.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ class Workflow < ApplicationRecord
44
belongs_to :user, counter_cache: :workflow_count, inverse_of: :workflows
55
has_many :workflow_memberships, dependent: :destroy, inverse_of: :workflow
66
has_many :agents, through: :workflow_memberships, inverse_of: :workflows
7+
has_many :messages, through: :agents
8+
has_many :logs, through: :agents
9+
710

811
validates :name, presence: true
912
validates :user, presence: true
@@ -20,6 +23,17 @@ class Workflow < ApplicationRecord
2023

2124
validate :agents_are_owned
2225

26+
def reset(erase_memory: false)
27+
# TODO: whould we disable all agents before resetting to prevent race
28+
# conditions?
29+
agents.each do |agent|
30+
agent.delete_logs!
31+
agent.messages.delete_all
32+
33+
agent.update!(memory: {}) if erase_memory
34+
end
35+
end
36+
2337
def destroy_with_mode(mode)
2438
case mode
2539
when 'all_agents'
@@ -43,6 +57,19 @@ def self.icons
4357
end
4458
end
4559

60+
# Development helpers #
61+
62+
# Delete all messages in all agents of this workflow
63+
def delete_all_messages
64+
Message.where(agent: agents).destroy_all
65+
end
66+
67+
# Delete all logs for all agents of this workflow
68+
def delete_all_logs
69+
AgentLog.where(agent: agents).destroy_all
70+
end
71+
72+
4673
private
4774

4875
def unique_agent_ids

app/views/workflows/_buttons.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
<%= link_to icon_tag('fa-trash-alt') + ' Delete', '#', data: { toggle: 'modal', target: "#confirm-workflow-deletion-#{@workflow.id}"}, class: "btn btn-primary btn-sm" %>
66
<%= link_to icon_tag('fa-play') + ' Enable all Agents', '#', data: { toggle: 'modal', target: "#enable-disable-agents"}, class: "btn btn-primary enable-all-agents btn-sm" %>
77
<%= link_to icon_tag('fa-pause') + ' Disable all Agents', '#', data: { toggle: 'modal', target: "#enable-disable-agents"}, class: "btn btn-primary disable-all-agents btn-sm" %>
8+
<%= link_to icon_tag('fa-recycle') + ' Reset Workflow' , '#', data: { toggle: 'modal', target: "#reset-workflow"}, class: "btn btn-primary btn-sm" %>
89
</div>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<div id="reset-workflow" class="modal fade" tabindex="-1" role="dialog">
2+
<div class="modal-dialog modal-lg">
3+
<div class="modal-content">
4+
<%= form_for(workflow, as: :workflow, url: reset_workflow_path(workflow), method: 'POST') do |f| %>
5+
<div class="modal-header">
6+
<h4 class="modal-title">Confirm resetting workflow</h4>
7+
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
8+
</div>
9+
<div class="modal-body">
10+
<div class="modal-body-action">
11+
Continuing will <span class="text-danger">erase all messages and logs</span>
12+
emited by the agents of this workflow.
13+
<br>
14+
<label>
15+
<input type="checkbox" name="erase_memory" value="1">
16+
also erase agent memory.
17+
</label>
18+
</div>
19+
<br>
20+
<% shared_agents = workflow.shared_agents %>
21+
<% unless shared_agents.empty? %>
22+
<% shared_agent_count = shared_agents.size.size # group statement %>
23+
<div class="text-danger">
24+
<%= t 'Agent', count: shared_agent_count %>
25+
<%= shared_agents.map { |agent| link_to(agent.name, agent_path(agent)) }.to_sentence.html_safe %>
26+
<%= t 'is', count: shared_agent_count %>
27+
shared with other workflows.
28+
Resetting <%= t 'it', count: shared_agent_count %>
29+
may disrupt other workflows.
30+
</div>
31+
<% end %>
32+
</div>
33+
<div class="modal-footer">
34+
<%= f.button 'No', class: 'btn btn-primary btn-sm', 'data-dismiss' => 'modal' %>
35+
<%= f.submit 'Yes', class: 'btn btn-primary btn-sm' %>
36+
</div>
37+
<% end %>
38+
</div>
39+
</div>
40+
</div>

app/views/workflows/show.html.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@
5353
</div>
5454
<%= render 'workflows/confirm_deletion_modal', workflow: @workflow %>
5555
<%= render 'workflows/enable_agents_modal', workflow: @workflow %>
56+
<%= render 'workflows/reset_modal', workflow: @workflow %>

config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
get :share
4949
get :export
5050
put :enable_or_disable_all_agents
51+
post :reset
5152
end
5253

5354
resource :diagram, only: [:show]

spec/controllers/workflows_controller_spec.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,25 @@ def valid_attributes(options = {})
134134
end
135135
end
136136

137+
describe 'POST reset' do
138+
it 'deletes all messages and logs' do
139+
@params = { 'commit' => 'Yes', 'id' => workflows(:bob_website).id }
140+
put :reset, params: @params
141+
aggregate_failures do
142+
expect(agents(:bob_website_agent).messages.count).to eq 0
143+
expect(agents(:bob_website_agent).logs.count).to eq 0
144+
end
145+
end
146+
147+
it 'erases agent memory if asked' do
148+
agents(:bob_website_agent).update(memory: { key: 'value' })
149+
@params = { 'erase_memory' => '1', 'commit' => 'Yes',
150+
'id' => workflows(:bob_website).id }
151+
put :reset, params: @params
152+
expect(agents(:bob_website_agent).reload.memory).to be_empty
153+
end
154+
end
155+
137156
describe 'DELETE destroy' do
138157
it 'destroys only Workflows owned by the current user' do
139158
expect {

spec/fixtures/workflow_memberships.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ bob_status_agent_workflow_membership:
1717
bob_notifier_agent_workflow_membership:
1818
agent: bob_notifier_agent
1919
workflow: bob_status
20+
21+
bob_website_agent_workflow_membership:
22+
agent: bob_website_agent
23+
workflow: bob_website

spec/fixtures/workflows.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,9 @@ bob_status:
1414
user: bob
1515
description: Bob's status alert system
1616
guid: random-guid-generated-by-jane
17+
18+
bob_website:
19+
name: Bob's website Workflow
20+
user: bob
21+
description: Bob's website check
22+
guid: random-guid-generated-by-bob2

spec/models/workflow_spec.rb

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,67 @@
9494
end
9595
end
9696

97+
98+
describe '#reset' do
99+
it 'deletes all messages' do
100+
agent1 = agents(:bob_status_agent)
101+
agent2 = agents(:bob_website_agent)
102+
agent1.workflows = [new_instance]
103+
agent2.workflows = [new_instance]
104+
10.times { Message.create(agent_id: agent1.id) }
105+
# agent2 already has one message
106+
107+
new_instance.reload
108+
109+
expect { new_instance.reset }
110+
.to change { new_instance.agents.map { |a| a.messages.count }.sum }
111+
.from(11)
112+
.to(0)
113+
end
114+
115+
it 'deletes all logs' do
116+
agent1 = agents(:bob_status_agent) # has 2 log entries
117+
agent2 = agents(:bob_website_agent) # has 1 log entry
118+
agent1.workflows = [new_instance]
119+
agent2.workflows = [new_instance]
120+
121+
new_instance.reload
122+
123+
expect { new_instance.reset }
124+
.to change { new_instance.agents.map { |a| a.logs.count }.sum }
125+
.from(3)
126+
.to(0)
127+
end
128+
129+
it 'preserves agent memory' do
130+
agent = agents(:bob_status_agent)
131+
agent.memory['last_status'] = '418'
132+
agent.workflows = [new_instance]
133+
agent.save
134+
135+
new_instance.reload
136+
137+
new_instance.reset
138+
139+
agent.reload
140+
141+
expect(agent.memory['last_status']).to eq '418'
142+
end
143+
144+
it 'erases agent memory if asked' do
145+
agent = agents(:bob_status_agent)
146+
agent.memory['last_status'] = '418'
147+
agent.workflows = [new_instance]
148+
agent.save
149+
150+
new_instance.reload
151+
152+
new_instance.reset(erase_memory: true)
153+
154+
expect(agent.reload.memory['last_status']).to be_nil
155+
end
156+
end
157+
97158
context '#destroy_with_mode' do
98159
it 'only destroys the workflow when no mode is passed' do
99160
expect { workflows(:jane_status).destroy_with_mode('') }.not_to change(Agent, :count)

0 commit comments

Comments
 (0)