promiscuous 0.90.0 → 0.91.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|