promiscuous 0.90.0 → 0.91.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/promiscuous/amqp/bunny.rb +63 -36
- data/lib/promiscuous/amqp/fake.rb +3 -1
- data/lib/promiscuous/amqp/hot_bunnies.rb +26 -16
- data/lib/promiscuous/amqp/null.rb +1 -0
- data/lib/promiscuous/amqp.rb +12 -12
- data/lib/promiscuous/cli.rb +70 -29
- data/lib/promiscuous/config.rb +54 -29
- data/lib/promiscuous/convenience.rb +1 -1
- data/lib/promiscuous/dependency.rb +25 -6
- data/lib/promiscuous/error/connection.rb +11 -9
- data/lib/promiscuous/error/dependency.rb +8 -1
- data/lib/promiscuous/loader.rb +4 -2
- data/lib/promiscuous/publisher/bootstrap/connection.rb +25 -0
- data/lib/promiscuous/publisher/bootstrap/data.rb +127 -0
- data/lib/promiscuous/publisher/bootstrap/mode.rb +19 -0
- data/lib/promiscuous/publisher/bootstrap/status.rb +40 -0
- data/lib/promiscuous/publisher/bootstrap/version.rb +46 -0
- data/lib/promiscuous/publisher/bootstrap.rb +27 -0
- data/lib/promiscuous/publisher/context/base.rb +67 -0
- data/lib/promiscuous/{middleware.rb → publisher/context/middleware.rb} +16 -13
- data/lib/promiscuous/publisher/context/transaction.rb +36 -0
- data/lib/promiscuous/publisher/context.rb +4 -88
- data/lib/promiscuous/publisher/mock_generator.rb +9 -9
- data/lib/promiscuous/publisher/model/active_record.rb +7 -7
- data/lib/promiscuous/publisher/model/base.rb +29 -29
- data/lib/promiscuous/publisher/model/ephemeral.rb +5 -3
- data/lib/promiscuous/publisher/model/mock.rb +9 -5
- data/lib/promiscuous/publisher/model/mongoid.rb +5 -22
- data/lib/promiscuous/publisher/operation/active_record.rb +360 -0
- data/lib/promiscuous/publisher/operation/atomic.rb +167 -0
- data/lib/promiscuous/publisher/operation/base.rb +279 -474
- data/lib/promiscuous/publisher/operation/mongoid.rb +153 -145
- data/lib/promiscuous/publisher/operation/non_persistent.rb +28 -0
- data/lib/promiscuous/publisher/operation/proxy_for_query.rb +42 -0
- data/lib/promiscuous/publisher/operation/transaction.rb +85 -0
- data/lib/promiscuous/publisher/operation.rb +1 -1
- data/lib/promiscuous/publisher/worker.rb +7 -7
- data/lib/promiscuous/publisher.rb +1 -1
- data/lib/promiscuous/railtie.rb +20 -5
- data/lib/promiscuous/redis.rb +104 -56
- data/lib/promiscuous/subscriber/message_processor/base.rb +38 -0
- data/lib/promiscuous/subscriber/message_processor/bootstrap.rb +17 -0
- data/lib/promiscuous/subscriber/message_processor/regular.rb +192 -0
- data/lib/promiscuous/subscriber/message_processor.rb +4 -0
- data/lib/promiscuous/subscriber/model/base.rb +20 -15
- data/lib/promiscuous/subscriber/model/mongoid.rb +4 -4
- data/lib/promiscuous/subscriber/model/observer.rb +16 -2
- data/lib/promiscuous/subscriber/operation/base.rb +68 -0
- data/lib/promiscuous/subscriber/operation/bootstrap.rb +54 -0
- data/lib/promiscuous/subscriber/operation/regular.rb +13 -0
- data/lib/promiscuous/subscriber/operation.rb +3 -166
- data/lib/promiscuous/subscriber/worker/message.rb +61 -35
- data/lib/promiscuous/subscriber/worker/message_synchronizer.rb +90 -59
- data/lib/promiscuous/subscriber/worker/pump.rb +17 -5
- data/lib/promiscuous/subscriber/worker/recorder.rb +4 -1
- data/lib/promiscuous/subscriber/worker/runner.rb +49 -9
- data/lib/promiscuous/subscriber/worker/stats.rb +2 -2
- data/lib/promiscuous/subscriber/worker.rb +6 -0
- data/lib/promiscuous/subscriber.rb +1 -1
- data/lib/promiscuous/timer.rb +31 -18
- data/lib/promiscuous/version.rb +1 -1
- data/lib/promiscuous.rb +23 -3
- metadata +104 -89
- data/lib/promiscuous/subscriber/payload.rb +0 -34
@@ -12,7 +12,7 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
12
12
|
@root = root
|
13
13
|
@node_synchronizers = {}
|
14
14
|
@lock = Mutex.new
|
15
|
-
@reconnect_timer = Promiscuous::Timer.new
|
15
|
+
@reconnect_timer = Promiscuous::Timer.new("redis", RECONNECT_INTERVAL) { reconnect }
|
16
16
|
end
|
17
17
|
|
18
18
|
def connected?
|
@@ -29,7 +29,11 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
29
29
|
redis.nodes.each { |node| @node_synchronizers[node] = NodeSynchronizer.new(self, node) }
|
30
30
|
@redis = redis
|
31
31
|
end
|
32
|
-
|
32
|
+
# Do not recover messages while bootstrapping as there are a very large
|
33
|
+
# number of messages that remain un-acked. If bootstrap messages are missed
|
34
|
+
# these will be caught in the final phase of bootstrapping (see
|
35
|
+
# Promiscuous::Subscriber::Operation).
|
36
|
+
@root.pump.recover unless Promiscuous::Config.bootstrap
|
33
37
|
end
|
34
38
|
|
35
39
|
def disconnect
|
@@ -51,14 +55,13 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
51
55
|
Promiscuous.warn "[redis] Reconnected"
|
52
56
|
end
|
53
57
|
|
54
|
-
def rescue_connection
|
55
|
-
|
58
|
+
def rescue_connection(node, exception)
|
59
|
+
# TODO stop the pump to unack all messages
|
60
|
+
@reconnect_timer.start
|
56
61
|
|
62
|
+
e = Promiscuous::Redis.lost_connection_exception(node, :inner => exception)
|
57
63
|
Promiscuous.warn "[redis] #{e}. Reconnecting..."
|
58
|
-
Promiscuous::Config.error_notifier.
|
59
|
-
|
60
|
-
# TODO stop the pump to unack all messages
|
61
|
-
@reconnect_timer.run_every(RECONNECT_INTERVAL) { reconnect }
|
64
|
+
Promiscuous::Config.error_notifier.call(e)
|
62
65
|
end
|
63
66
|
|
64
67
|
# process_when_ready() is called by the AMQP pump. This is what happens:
|
@@ -67,32 +70,33 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
67
70
|
# If not we bail out and rely on the subscription to kick the processing.
|
68
71
|
# Because we subscribed in advanced, we will not miss the notification.
|
69
72
|
def process_when_ready(msg)
|
73
|
+
unless msg.has_dependencies?
|
74
|
+
process_message!(msg)
|
75
|
+
return
|
76
|
+
end
|
77
|
+
|
70
78
|
# Dropped messages will be redelivered as we (re)connect
|
71
79
|
return unless self.redis
|
72
80
|
|
73
|
-
@lock.synchronize
|
74
|
-
@num_queued_messages += 1
|
75
|
-
end
|
81
|
+
@lock.synchronize { @num_queued_messages += 1 }
|
76
82
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end.call
|
88
|
-
else
|
89
|
-
process_message!(msg)
|
90
|
-
end
|
83
|
+
process_message_proc = proc { process_message!(msg) }
|
84
|
+
msg.happens_before_dependencies.reduce(process_message_proc) do |chain, dep|
|
85
|
+
get_redis = dep.redis_node
|
86
|
+
subscriber_redis = dep.redis_node(@redis)
|
87
|
+
|
88
|
+
key = dep.key(:sub).join('rw').to_s
|
89
|
+
version = dep.version
|
90
|
+
node_synchronizer = @node_synchronizers[subscriber_redis]
|
91
|
+
proc { node_synchronizer.on_version(subscriber_redis, get_redis, key, version, msg) { chain.call } }
|
92
|
+
end.call
|
91
93
|
end
|
92
94
|
|
93
95
|
def process_message!(msg)
|
94
96
|
@root.runner.messages_to_process << msg
|
95
97
|
|
98
|
+
return unless msg.has_dependencies?
|
99
|
+
|
96
100
|
cleanup = false
|
97
101
|
@lock.synchronize do
|
98
102
|
@num_queued_messages -= 1
|
@@ -108,38 +112,57 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
108
112
|
# We also know that we are not processing messages (@num_queued_messages is
|
109
113
|
# decremented before we send the message to the runners), and we are called
|
110
114
|
# after adding a pending callback.
|
111
|
-
|
115
|
+
recover_dependencies_for(blocked_messages.first)
|
112
116
|
end
|
113
117
|
end
|
114
118
|
|
115
|
-
def
|
119
|
+
def recover_dependencies_for(msg)
|
116
120
|
# XXX This recovery mechanism only works with one worker.
|
117
121
|
# We are taking the earliest message to unblock, but in reality we should
|
118
122
|
# do the DAG of the happens before dependencies, take root nodes
|
119
123
|
# of the disconnected graphs, and sort by timestamps if needed.
|
120
|
-
msg = blocked_messages.first
|
121
124
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
125
|
+
incremented_deps = {}
|
126
|
+
|
127
|
+
msg.happens_before_dependencies.each do |dep|
|
128
|
+
key = dep.key(:sub).join('rw')
|
129
|
+
guard_key = key.join('guard') if dep.write?
|
130
|
+
version = dep.version
|
127
131
|
|
128
|
-
|
132
|
+
@@version_recovery_script ||= Promiscuous::Redis::Script.new <<-SCRIPT
|
133
|
+
local key = ARGV[1]
|
134
|
+
local wanted_version = tonumber(ARGV[2])
|
135
|
+
local guard_key = ARGV[3]
|
129
136
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
137
|
+
if redis.call('exists', guard_key) == 1 then
|
138
|
+
return
|
139
|
+
end
|
140
|
+
|
141
|
+
local current_version = tonumber(redis.call('get', key)) or 0
|
142
|
+
|
143
|
+
if wanted_version > current_version then
|
144
|
+
redis.call('set', guard_key, 1)
|
145
|
+
redis.call('expire', guard_key, 10)
|
146
|
+
|
147
|
+
redis.call('set', key, wanted_version)
|
148
|
+
redis.call('publish', key, wanted_version)
|
149
|
+
return wanted_version - current_version
|
150
|
+
end
|
151
|
+
SCRIPT
|
152
|
+
increment = @@version_recovery_script.eval(dep.redis_node, :argv => [key, version, guard_key].compact)
|
153
|
+
incremented_deps[dep] = increment if increment
|
154
|
+
end
|
134
155
|
|
135
|
-
|
136
|
-
|
137
|
-
|
156
|
+
if incremented_deps.present?
|
157
|
+
recovery_msg = "Incrementing "
|
158
|
+
recovery_msg += incremented_deps.map { |dep, increment| "#{dep} by #{increment}" }.join(", ")
|
138
159
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
160
|
+
e = Promiscuous::Error::Recovery.new(recovery_msg)
|
161
|
+
Promiscuous.error "[synchronization recovery] #{e}"
|
162
|
+
|
163
|
+
# TODO Should we report the error to the notifier, or the log file is enough?
|
164
|
+
# Promiscuous::Config.error_notifier.call(e)
|
165
|
+
end
|
143
166
|
end
|
144
167
|
|
145
168
|
def blocked_messages
|
@@ -150,10 +173,6 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
150
173
|
.sort_by { |msg| msg.timestamp }
|
151
174
|
end
|
152
175
|
|
153
|
-
def not_recovering
|
154
|
-
Promiscuous.warn "[synchronization recovery] Nothing to recover from"
|
155
|
-
end
|
156
|
-
|
157
176
|
class NodeSynchronizer
|
158
177
|
attr_accessor :node, :subscriptions, :root_synchronizer
|
159
178
|
|
@@ -181,16 +200,16 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
181
200
|
notify_key_change(subscription, arg)
|
182
201
|
end
|
183
202
|
end
|
184
|
-
rescue EOFError, Errno::ECONNRESET
|
203
|
+
rescue EOFError, Errno::ECONNRESET => e
|
185
204
|
# Unwanted disconnection
|
186
|
-
@root_synchronizer.rescue_connection unless @stop
|
187
|
-
rescue IOError => e
|
188
|
-
raise e unless @stop
|
205
|
+
@root_synchronizer.rescue_connection(redis_client, e) unless @stop
|
189
206
|
rescue Exception => e
|
190
|
-
|
191
|
-
|
207
|
+
unless @stop
|
208
|
+
Promiscuous.warn "[redis] #{e.class} #{e.message}"
|
209
|
+
Promiscuous.warn "[redis] #{e}\n#{e.backtrace.join("\n")}"
|
192
210
|
|
193
|
-
|
211
|
+
Promiscuous::Config.error_notifier.call(e)
|
212
|
+
end
|
194
213
|
end
|
195
214
|
|
196
215
|
def stop_main_loop
|
@@ -270,6 +289,17 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
270
289
|
refresh_activity
|
271
290
|
end
|
272
291
|
|
292
|
+
def with_rescue_connection(node, &block)
|
293
|
+
block.call
|
294
|
+
rescue Exception => e
|
295
|
+
# TODO only catch exceptions related to network issues
|
296
|
+
node_synchronizer.root_synchronizer.rescue_connection(node, e)
|
297
|
+
end
|
298
|
+
|
299
|
+
def redis_exec_raw(node, *commands)
|
300
|
+
with_rescue_connection(node) { node.client.process([commands]) }
|
301
|
+
end
|
302
|
+
|
273
303
|
def total_num_processed_messages
|
274
304
|
node_synchronizer.root_synchronizer.num_processed_messages
|
275
305
|
end
|
@@ -285,7 +315,7 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
285
315
|
|
286
316
|
def cleanup_if_old
|
287
317
|
if is_old?
|
288
|
-
subscriber_redis
|
318
|
+
redis_exec_raw(subscriber_redis, :unsubscribe, key)
|
289
319
|
node_synchronizer.subscriptions.delete(key) # lock is already held
|
290
320
|
end
|
291
321
|
end
|
@@ -296,11 +326,12 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
296
326
|
@subscription_requested = true
|
297
327
|
end
|
298
328
|
|
299
|
-
subscriber_redis
|
329
|
+
redis_exec_raw(subscriber_redis, :subscribe, key)
|
300
330
|
end
|
301
331
|
|
302
332
|
def finalize_subscription
|
303
|
-
|
333
|
+
v = with_rescue_connection(get_redis) { get_redis.get(key) }
|
334
|
+
signal_version(v)
|
304
335
|
end
|
305
336
|
|
306
337
|
def signal_version(current_version)
|
@@ -8,17 +8,29 @@ class Promiscuous::Subscriber::Worker::Pump
|
|
8
8
|
|
9
9
|
def connect
|
10
10
|
options = {}
|
11
|
-
options[:
|
11
|
+
options[:bindings] = {}
|
12
12
|
# We need to subscribe to everything to keep up with the version tracking
|
13
|
-
|
13
|
+
Promiscuous::Config.subscriber_exchanges.each do |exchange|
|
14
|
+
options[:bindings][exchange] = ['*']
|
15
|
+
end
|
16
|
+
|
17
|
+
if Promiscuous::Config.bootstrap
|
18
|
+
options[:bindings][Promiscuous::AMQP::BOOTSTRAP_EXCHANGE] = ['*']
|
19
|
+
end
|
20
|
+
|
14
21
|
subscribe(options, &method(:on_message))
|
15
22
|
end
|
16
23
|
|
17
24
|
def on_message(metadata, payload)
|
18
25
|
msg = Promiscuous::Subscriber::Worker::Message.new(payload, :metadata => metadata, :root_worker => @root)
|
19
|
-
|
26
|
+
if Promiscuous::Config.bootstrap
|
27
|
+
# Bootstrapping doesn't require synchronzation
|
28
|
+
@root.runner.messages_to_process << msg
|
29
|
+
else
|
30
|
+
@root.message_synchronizer.process_when_ready(msg)
|
31
|
+
end
|
20
32
|
rescue Exception => e
|
21
|
-
Promiscuous.warn "[receive] cannot process message: #{e}
|
22
|
-
Promiscuous::Config.error_notifier.
|
33
|
+
Promiscuous.warn "[receive] cannot process message: #{e}\n#{e.backtrace.join("\n")}"
|
34
|
+
Promiscuous::Config.error_notifier.call(e)
|
23
35
|
end
|
24
36
|
end
|
@@ -8,8 +8,11 @@ class Promiscuous::Subscriber::Worker::Recorder
|
|
8
8
|
@file = File.open(@log_file, 'a')
|
9
9
|
options = {}
|
10
10
|
options[:queue_name] = "#{Promiscuous::Config.app}.promiscuous"
|
11
|
+
options[:bindings] = {}
|
11
12
|
# We need to subscribe to everything to keep up with the version tracking
|
12
|
-
|
13
|
+
Promiscuous::Config.subscriber_exchanges.each do |exchange|
|
14
|
+
options[:bindings][exchange] = ['*']
|
15
|
+
end
|
13
16
|
|
14
17
|
subscribe(options) do |metadata, payload|
|
15
18
|
@file.puts payload
|
@@ -8,21 +8,61 @@ class Promiscuous::Subscriber::Worker::Runner
|
|
8
8
|
|
9
9
|
def start
|
10
10
|
num_threads = Promiscuous::Config.subscriber_threads
|
11
|
-
@
|
12
|
-
@threads ||= num_threads.times.map { |i| Thread.new { main_loop(@locks[i]) } }
|
11
|
+
@runner_threads ||= num_threads.times.map { RunnerThread.new(@messages_to_process) }
|
13
12
|
end
|
14
13
|
|
15
14
|
def stop
|
16
|
-
return unless @
|
17
|
-
|
18
|
-
@
|
15
|
+
return unless @runner_threads
|
16
|
+
|
17
|
+
@runner_threads.each { |runner_thread| runner_thread.stop }
|
18
|
+
@runner_threads = nil
|
19
|
+
|
19
20
|
@messages_to_process.clear
|
20
21
|
end
|
21
22
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
def show_stop_status(num_requests)
|
24
|
+
@runner_threads.each { |runner_thread| runner_thread.show_stop_status(num_requests) }
|
25
|
+
end
|
26
|
+
|
27
|
+
class RunnerThread
|
28
|
+
def initialize(message_queue)
|
29
|
+
@message_queue = message_queue
|
30
|
+
@kill_lock = Mutex.new
|
31
|
+
@thread = Thread.new { main_loop }
|
32
|
+
end
|
33
|
+
|
34
|
+
def main_loop
|
35
|
+
loop do
|
36
|
+
msg = @message_queue.pop
|
37
|
+
@kill_lock.synchronize do
|
38
|
+
@current_message = msg
|
39
|
+
msg.process # msg.process does not throw
|
40
|
+
@current_message = nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def stop
|
46
|
+
@kill_lock.synchronize { @thread.kill }
|
47
|
+
end
|
48
|
+
|
49
|
+
def show_stop_status(num_requests)
|
50
|
+
msg = @current_message
|
51
|
+
backtrace = @thread.backtrace
|
52
|
+
|
53
|
+
if msg
|
54
|
+
STDERR.puts "Still processing #{msg.payload}"
|
55
|
+
|
56
|
+
if num_requests > 1 && backtrace
|
57
|
+
STDERR.puts
|
58
|
+
STDERR.puts backtrace.map { |line| " \e[1;30m#{line}\e[0m\n" }
|
59
|
+
STDERR.puts
|
60
|
+
STDERR.puts "I'm a little busy, check out my stack trace."
|
61
|
+
STDERR.puts "Be patient (or kill me with -9, but that wouldn't be very nice of you)."
|
62
|
+
else
|
63
|
+
STDERR.puts "Just a second..."
|
64
|
+
end
|
65
|
+
end
|
26
66
|
end
|
27
67
|
end
|
28
68
|
end
|
@@ -15,8 +15,8 @@ class Promiscuous::Subscriber::Worker::Stats
|
|
15
15
|
|
16
16
|
STDERR.puts ""
|
17
17
|
|
18
|
-
@timer ||= Promiscuous::Timer.new
|
19
|
-
@timer.
|
18
|
+
@timer ||= Promiscuous::Timer.new("stats", @interval) { aggregate_stats }
|
19
|
+
@timer.start
|
20
20
|
end
|
21
21
|
|
22
22
|
def disconnect
|
@@ -24,4 +24,10 @@ class Promiscuous::Subscriber::Worker
|
|
24
24
|
@pump.disconnect
|
25
25
|
@message_synchronizer.disconnect
|
26
26
|
end
|
27
|
+
|
28
|
+
def show_stop_status
|
29
|
+
@num_show_stop_requests ||= 0
|
30
|
+
@num_show_stop_requests += 1
|
31
|
+
@runner.show_stop_status(@num_show_stop_requests)
|
32
|
+
end
|
27
33
|
end
|
data/lib/promiscuous/timer.rb
CHANGED
@@ -1,32 +1,44 @@
|
|
1
1
|
class Promiscuous::Timer
|
2
|
-
def initialize
|
2
|
+
def initialize(name, duration, &block)
|
3
|
+
@name = name
|
4
|
+
@duration = duration.to_f
|
5
|
+
@block = block
|
3
6
|
@lock = Mutex.new
|
4
7
|
end
|
5
8
|
|
6
|
-
def
|
9
|
+
def run_callback
|
10
|
+
@block.call
|
11
|
+
rescue Exception => e
|
12
|
+
# Report the exception only once
|
13
|
+
unless @last_exception == e.to_s
|
14
|
+
@last_exception = e.to_s
|
15
|
+
Promiscuous.warn "[#{@name}] #{e}"
|
16
|
+
Promiscuous::Config.error_notifier.call(e)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def main_loop(options={})
|
21
|
+
Thread.current[:promiscuous_timer_instance] = self
|
7
22
|
options = options.dup
|
8
|
-
duration = duration.to_f unless duration.is_a?(Integer)
|
9
|
-
reset
|
10
23
|
|
11
|
-
|
12
|
-
@
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
if @thread == Thread.current
|
17
|
-
begin
|
18
|
-
block.call
|
19
|
-
rescue Exception
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
+
loop do
|
25
|
+
sleep @duration unless options.delete(:run_immediately)
|
26
|
+
@lock.synchronize do
|
27
|
+
return unless @thread
|
28
|
+
run_callback
|
24
29
|
end
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
33
|
+
def start(options={})
|
34
|
+
@lock.synchronize do
|
35
|
+
@thread ||= Thread.new { main_loop(options) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
28
39
|
def reset
|
29
|
-
if
|
40
|
+
if Thread.current[:promiscuous_timer_instance] == self
|
41
|
+
# We already hold the lock (the callback called reset)
|
30
42
|
@thread = nil
|
31
43
|
else
|
32
44
|
@lock.synchronize do
|
@@ -34,5 +46,6 @@ class Promiscuous::Timer
|
|
34
46
|
@thread = nil
|
35
47
|
end
|
36
48
|
end
|
49
|
+
@last_exception = nil
|
37
50
|
end
|
38
51
|
end
|
data/lib/promiscuous/version.rb
CHANGED
data/lib/promiscuous.rb
CHANGED
@@ -18,7 +18,10 @@ module Promiscuous
|
|
18
18
|
extend Promiscuous::Autoload
|
19
19
|
autoload :Common, :Publisher, :Subscriber, :Observer, :Worker, :Ephemeral,
|
20
20
|
:CLI, :Error, :Loader, :AMQP, :Redis, :ZK, :Config, :DSL, :Key,
|
21
|
-
:Convenience, :Dependency, :
|
21
|
+
:Convenience, :Dependency, :Timer
|
22
|
+
|
23
|
+
# Shortcut for the middleware, TODO make load on demand
|
24
|
+
Middleware = Publisher::Context::Middleware
|
22
25
|
|
23
26
|
extend Promiscuous::DSL
|
24
27
|
|
@@ -38,11 +41,17 @@ module Promiscuous
|
|
38
41
|
def connect
|
39
42
|
AMQP.connect
|
40
43
|
Redis.connect
|
44
|
+
@should_be_connected = true
|
41
45
|
end
|
42
46
|
|
43
47
|
def disconnect
|
44
48
|
AMQP.disconnect
|
45
49
|
Redis.disconnect
|
50
|
+
@should_be_connected = false
|
51
|
+
end
|
52
|
+
|
53
|
+
def should_be_connected?
|
54
|
+
!!@should_be_connected
|
46
55
|
end
|
47
56
|
|
48
57
|
def healthy?
|
@@ -54,16 +63,27 @@ module Promiscuous
|
|
54
63
|
true
|
55
64
|
end
|
56
65
|
|
66
|
+
def ensure_connected
|
67
|
+
unless should_be_connected?
|
68
|
+
connect
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
57
72
|
def disabled
|
58
|
-
Thread.current[:promiscuous_disabled]
|
73
|
+
return $promiscuous_disabled if Thread.current[:promiscuous_disabled].nil?
|
74
|
+
Thread.current[:promiscuous_disabled]
|
59
75
|
end
|
60
76
|
|
61
77
|
def disabled=(value)
|
62
78
|
Thread.current[:promiscuous_disabled] = value
|
63
79
|
end
|
64
80
|
|
81
|
+
def disabled?
|
82
|
+
!!Thread.current[:promiscuous_disabled]
|
83
|
+
end
|
84
|
+
|
65
85
|
def context(*args, &block)
|
66
|
-
Publisher::Context.
|
86
|
+
Publisher::Context::Base.with_context(*args, &block)
|
67
87
|
end
|
68
88
|
end
|
69
89
|
|