Merge pull request #1158 from cantino/prevent_extra_threads_in_specs

Prevent buildup of threads in specs

Andrew Cantino vor 8 Jahren
Ursprung
Commit
e624815eb7

+ 5 - 2
app/concerns/long_runnable.rb

@@ -97,8 +97,10 @@ module LongRunnable
97 97
     end
98 98
 
99 99
     def terminate_thread!
100
-      thread.terminate
101
-      thread.wakeup if thread.status == 'sleep'
100
+      if thread
101
+        thread.terminate
102
+        thread.wakeup if thread.status == 'sleep'
103
+      end
102 104
     end
103 105
 
104 106
     def restart!
@@ -126,6 +128,7 @@ module LongRunnable
126 128
     end
127 129
 
128 130
     private
131
+
129 132
     def schedule(method, args, &blk)
130 133
       @scheduler.send(method, *args, tag: id, &blk)
131 134
     end

+ 6 - 5
lib/agent_runner.rb

@@ -28,7 +28,7 @@ class AgentRunner
28 28
   end
29 29
 
30 30
   def stop
31
-    puts "Stopping AgentRunner..."
31
+    puts "Stopping AgentRunner..." unless Rails.env.test?
32 32
     @running = false
33 33
     @workers.each_pair do |_, w| w.stop! end
34 34
     @scheduler.stop
@@ -64,19 +64,20 @@ class AgentRunner
64 64
   end
65 65
 
66 66
   private
67
+
67 68
   def run_workers
68 69
     workers             = load_workers
69 70
     new_worker_ids      = workers.keys
70 71
     current_worker_ids  = @workers.keys
71 72
 
72 73
     (current_worker_ids - new_worker_ids).each do |outdated_worker_id|
73
-      puts "Killing #{outdated_worker_id}"
74
+      puts "Killing #{outdated_worker_id}" unless Rails.env.test?
74 75
       @workers[outdated_worker_id].stop!
75 76
       @workers.delete(outdated_worker_id)
76 77
     end
77 78
 
78 79
     (new_worker_ids - current_worker_ids).each do |new_worker_id|
79
-      puts "Starting #{new_worker_id}"
80
+      puts "Starting #{new_worker_id}" unless Rails.env.test?
80 81
       @workers[new_worker_id] = workers[new_worker_id]
81 82
       @workers[new_worker_id].setup!(@scheduler, @mutex)
82 83
       @workers[new_worker_id].run!
@@ -101,7 +102,7 @@ class AgentRunner
101 102
   def restart_dead_workers
102 103
     @workers.each_pair do |id, worker|
103 104
       if !worker.restarting && worker.thread && !worker.thread.alive?
104
-        puts "Restarting #{id.to_s}"
105
+        puts "Restarting #{id.to_s}" unless Rails.env.test?
105 106
         @workers[id].run!
106 107
       end
107 108
     end
@@ -118,4 +119,4 @@ end
118 119
 require 'agents/twitter_stream_agent'
119 120
 require 'agents/jabber_agent'
120 121
 require 'huginn_scheduler'
121
-require 'delayed_job_worker'
122
+require 'delayed_job_worker'

+ 1 - 1
lib/delayed_job_worker.rb

@@ -7,7 +7,7 @@ class DelayedJobWorker < LongRunnable::Worker
7 7
   end
8 8
 
9 9
   def stop
10
-    @dj.stop
10
+    @dj.stop if @dj
11 11
   end
12 12
 
13 13
   def self.setup_worker

+ 1 - 0
lib/huginn_scheduler.rb

@@ -145,6 +145,7 @@ class HuginnScheduler < LongRunnable::Worker
145 145
   end
146 146
 
147 147
   private
148
+
148 149
   def run_schedule(time)
149 150
     with_mutex do
150 151
       puts "Queuing schedule for #{time}"

+ 31 - 11
spec/concerns/long_runnable_spec.rb

@@ -9,7 +9,7 @@ describe LongRunnable do
9 9
     end
10 10
   end
11 11
 
12
-  before(:all) do
12
+  before(:each) do
13 13
     @agent = LongRunnableAgent.new
14 14
   end
15 15
 
@@ -41,7 +41,13 @@ describe LongRunnable do
41 41
     before(:each) do
42 42
       @agent = Object.new
43 43
       @worker = LongRunnable::Worker.new(agent: @agent, id: 'test1234')
44
-      @worker.setup!(Rufus::Scheduler.new, Mutex.new)
44
+      @scheduler = Rufus::Scheduler.new
45
+      @worker.setup!(@scheduler, Mutex.new)
46
+    end
47
+
48
+    after(:each) do
49
+      @worker.thread.terminate if @worker.thread && !@skip_thread_terminate
50
+      @scheduler.shutdown(:wait)
45 51
     end
46 52
 
47 53
     it "calls boolify of the agent" do
@@ -75,21 +81,35 @@ describe LongRunnable do
75 81
 
76 82
     context "#stop!" do
77 83
       it "terminates the thread" do
84
+        mock.proxy(@worker).terminate_thread!
85
+        @worker.stop!
86
+      end
87
+
88
+      it "gracefully stops the worker" do
89
+        mock(@worker).stop
90
+        @worker.stop!
91
+      end
92
+    end
93
+
94
+    context "#terminate_thread!" do
95
+      before do
96
+        @skip_thread_terminate = true
97
+        mock_thread = Object.new
98
+        stub(@worker).thread { mock_thread }
99
+      end
100
+
101
+      it "terminates the thread" do
78 102
         mock(@worker.thread).terminate
103
+        do_not_allow(@worker.thread).wakeup
79 104
         mock(@worker.thread).status { 'run' }
80
-        @worker.stop!
105
+        @worker.terminate_thread!
81 106
       end
82 107
 
83 108
       it "wakes up sleeping threads after termination" do
84 109
         mock(@worker.thread).terminate
85
-        mock(@worker.thread).status { 'sleep' }
86 110
         mock(@worker.thread).wakeup
87
-        @worker.stop!
88
-      end
89
-
90
-      it "gracefully stops the worker" do
91
-        mock(@worker).stop
92
-        @worker.stop!
111
+        mock(@worker.thread).status { 'sleep' }
112
+        @worker.terminate_thread!
93 113
       end
94 114
     end
95 115
 
@@ -119,4 +139,4 @@ describe LongRunnable do
119 139
       end
120 140
     end
121 141
   end
122
-end
142
+end

+ 17 - 8
spec/lib/agent_runner_spec.rb

@@ -8,10 +8,14 @@ describe AgentRunner do
8 8
       @agent_runner = AgentRunner.new
9 9
     end
10 10
 
11
+    after(:each) do
12
+      @agent_runner.stop
13
+      AgentRunner.class_variable_set(:@@agents, [])
14
+    end
15
+
11 16
     context "#run" do
12 17
       before do
13 18
         mock(@agent_runner).run_workers
14
-        mock.instance_of(IO).puts('Stopping AgentRunner...')
15 19
       end
16 20
 
17 21
       it "runs until stop is called" do
@@ -30,6 +34,7 @@ describe AgentRunner do
30 34
       before do
31 35
         AgentRunner.class_variable_set(:@@agents, [HuginnScheduler, DelayedJobWorker])
32 36
       end
37
+
33 38
       it "loads all workers" do
34 39
         workers = @agent_runner.send(:load_workers)
35 40
         expect(workers).to be_a(Hash)
@@ -37,27 +42,29 @@ describe AgentRunner do
37 42
       end
38 43
 
39 44
       it "loads only the workers specified in the :only option" do
40
-        @agent_runner = AgentRunner.new(only: HuginnScheduler)
41
-        workers = @agent_runner.send(:load_workers)
45
+        agent_runner = AgentRunner.new(only: HuginnScheduler)
46
+        workers = agent_runner.send(:load_workers)
42 47
         expect(workers.keys).to eq(['HuginnScheduler'])
48
+        agent_runner.stop
43 49
       end
44 50
 
45 51
       it "does not load workers specified in the :except option" do
46
-        @agent_runner = AgentRunner.new(except: HuginnScheduler)
47
-        workers = @agent_runner.send(:load_workers)
52
+        agent_runner = AgentRunner.new(except: HuginnScheduler)
53
+        workers = agent_runner.send(:load_workers)
48 54
         expect(workers.keys).to eq(['DelayedJobWorker'])
55
+
56
+        agent_runner.stop
49 57
       end
50 58
     end
51 59
 
52 60
     context "running workers" do
53 61
       before do
54 62
         AgentRunner.class_variable_set(:@@agents, [HuginnScheduler, DelayedJobWorker])
55
-        stub.instance_of(IO).puts
56
-        stub.instance_of(LongRunnable::Worker).setup!
63
+        stub.instance_of(HuginnScheduler).setup
64
+        stub.instance_of(DelayedJobWorker).setup
57 65
       end
58 66
 
59 67
       context "#run_workers" do
60
-
61 68
         it "runs all the workers" do
62 69
           mock.instance_of(HuginnScheduler).run!
63 70
           mock.instance_of(DelayedJobWorker).run!
@@ -97,6 +104,8 @@ describe AgentRunner do
97 104
       mock(Signal).trap('TERM')
98 105
       mock(Signal).trap('QUIT')
99 106
       agent_runner.set_traps
107
+
108
+      agent_runner.stop
100 109
     end
101 110
   end
102 111
 end

+ 0 - 2
spec/lib/agents_exporter_spec.rb

@@ -1,5 +1,3 @@
1
-# encoding: utf-8
2
-
3 1
 require 'rails_helper'
4 2
 
5 3
 describe AgentsExporter do

+ 11 - 5
spec/lib/huginn_scheduler_spec.rb

@@ -3,16 +3,20 @@ require 'huginn_scheduler'
3 3
 
4 4
 describe HuginnScheduler do
5 5
   before(:each) do
6
+    @rufus_scheduler = Rufus::Scheduler.new
6 7
     @scheduler = HuginnScheduler.new
7 8
     stub(@scheduler).setup {}
8
-    @scheduler.setup!(Rufus::Scheduler.new, Mutex.new)
9
-    stub
9
+    @scheduler.setup!(@rufus_scheduler, Mutex.new)
10
+  end
11
+
12
+  after(:each) do
13
+    @rufus_scheduler.shutdown(:wait)
10 14
   end
11 15
 
12 16
   it "schould register the schedules with the rufus scheduler and run" do
13
-    mock.instance_of(Rufus::Scheduler).join
17
+    mock(@rufus_scheduler).join
14 18
     scheduler = HuginnScheduler.new
15
-    scheduler.setup!(Rufus::Scheduler.new, Mutex.new)
19
+    scheduler.setup!(@rufus_scheduler, Mutex.new)
16 20
     scheduler.run
17 21
   end
18 22
 
@@ -87,6 +91,8 @@ end
87 91
 
88 92
 describe Rufus::Scheduler do
89 93
   before :each do
94
+    Agent.delete_all
95
+
90 96
     @taoe, Thread.abort_on_exception = Thread.abort_on_exception, false
91 97
     @oso, @ose, $stdout, $stderr = $stdout, $stderr, StringIO.new, StringIO.new
92 98
 
@@ -105,7 +111,7 @@ describe Rufus::Scheduler do
105 111
   end
106 112
 
107 113
   after :each do
108
-    @scheduler.shutdown
114
+    @scheduler.shutdown(:wait)
109 115
 
110 116
     Thread.abort_on_exception = @taoe
111 117
     $stdout, $stderr = @oso, @ose

+ 1 - 2
spec/models/agents/twitter_stream_agent_spec.rb

@@ -192,8 +192,7 @@ describe Agents::TwitterStreamAgent do
192 192
 
193 193
     context "#stop" do
194 194
       it "stops the thread" do
195
-        mock(@worker.thread).terminate
196
-        mock(@worker.thread).status
195
+        mock(@worker).terminate_thread!
197 196
         @worker.stop
198 197
       end
199 198
     end