@@ -51,12 +51,13 @@ module LongRunnable |
||
51 | 51 |
end |
52 | 52 |
|
53 | 53 |
class Worker |
54 |
- attr_reader :thread, :id, :agent, :config, :mutex, :scheduler |
|
54 |
+ attr_reader :thread, :id, :agent, :config, :mutex, :scheduler, :restarting |
|
55 | 55 |
|
56 | 56 |
def initialize(options = {}) |
57 | 57 |
@id = options[:id] |
58 | 58 |
@agent = options[:agent] |
59 | 59 |
@config = options[:config] |
60 |
+ @restarting = false |
|
60 | 61 |
end |
61 | 62 |
|
62 | 63 |
def run |
@@ -65,6 +66,7 @@ module LongRunnable |
||
65 | 66 |
|
66 | 67 |
def run! |
67 | 68 |
@thread = Thread.new do |
69 |
+ Thread.current[:name] = "#{id}-#{Time.now}" |
|
68 | 70 |
begin |
69 | 71 |
run |
70 | 72 |
rescue SignalException, SystemExit |
@@ -90,14 +92,21 @@ module LongRunnable |
||
90 | 92 |
if respond_to?(:stop) |
91 | 93 |
stop |
92 | 94 |
else |
93 |
- thread.terminate |
|
95 |
+ terminate_thread! |
|
94 | 96 |
end |
95 | 97 |
end |
96 | 98 |
|
99 |
+ def terminate_thread! |
|
100 |
+ thread.terminate |
|
101 |
+ thread.wakeup if thread.status == 'sleep' |
|
102 |
+ end |
|
103 |
+ |
|
97 | 104 |
def restart! |
98 |
- stop! |
|
99 |
- setup!(scheduler, mutex) |
|
100 |
- run! |
|
105 |
+ without_alive_check do |
|
106 |
+ stop! |
|
107 |
+ setup!(scheduler, mutex) |
|
108 |
+ run! |
|
109 |
+ end |
|
101 | 110 |
end |
102 | 111 |
|
103 | 112 |
def every(*args, &blk) |
@@ -120,5 +129,12 @@ module LongRunnable |
||
120 | 129 |
def schedule(method, args, &blk) |
121 | 130 |
@scheduler.send(method, *args, tag: id, &blk) |
122 | 131 |
end |
132 |
+ |
|
133 |
+ def without_alive_check(&blk) |
|
134 |
+ @restarting = true |
|
135 |
+ yield |
|
136 |
+ ensure |
|
137 |
+ @restarting = false |
|
138 |
+ end |
|
123 | 139 |
end |
124 | 140 |
end |
@@ -176,7 +176,7 @@ module Agents |
||
176 | 176 |
|
177 | 177 |
def stop |
178 | 178 |
EventMachine.stop_event_loop if EventMachine.reactor_running? |
179 |
- thread.terminate |
|
179 |
+ terminate_thread! |
|
180 | 180 |
end |
181 | 181 |
|
182 | 182 |
private |
@@ -100,7 +100,7 @@ class AgentRunner |
||
100 | 100 |
|
101 | 101 |
def restart_dead_workers |
102 | 102 |
@workers.each_pair do |id, worker| |
103 |
- if worker.thread && !worker.thread.alive? |
|
103 |
+ if !worker.restarting && worker.thread && !worker.thread.alive? |
|
104 | 104 |
puts "Restarting #{id.to_s}" |
105 | 105 |
@workers[id].run! |
106 | 106 |
end |
@@ -76,6 +76,14 @@ describe LongRunnable do |
||
76 | 76 |
context "#stop!" do |
77 | 77 |
it "terminates the thread" do |
78 | 78 |
mock(@worker.thread).terminate |
79 |
+ mock(@worker.thread).status { 'run' } |
|
80 |
+ @worker.stop! |
|
81 |
+ end |
|
82 |
+ |
|
83 |
+ it "wakes up sleeping threads after termination" do |
|
84 |
+ mock(@worker.thread).terminate |
|
85 |
+ mock(@worker.thread).status { 'sleep' } |
|
86 |
+ mock(@worker.thread).wakeup |
|
79 | 87 |
@worker.stop! |
80 | 88 |
end |
81 | 89 |
|
@@ -193,6 +193,7 @@ describe Agents::TwitterStreamAgent do |
||
193 | 193 |
context "#stop" do |
194 | 194 |
it "stops the thread" do |
195 | 195 |
mock(@worker.thread).terminate |
196 |
+ mock(@worker.thread).status |
|
196 | 197 |
@worker.stop |
197 | 198 |
end |
198 | 199 |
end |