promiscuous 0.50.4 → 0.51.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.
- data/lib/promiscuous.rb +24 -0
- data/lib/promiscuous/amqp/ruby_amqp.rb +3 -1
- data/lib/promiscuous/cli.rb +14 -6
- data/lib/promiscuous/config.rb +7 -2
- data/lib/promiscuous/error.rb +1 -1
- data/lib/promiscuous/error/recover.rb +1 -0
- data/lib/promiscuous/subscriber/worker/message_synchronizer.rb +73 -1
- data/lib/promiscuous/version.rb +1 -1
- metadata +6 -5
data/lib/promiscuous.rb
CHANGED
@@ -46,5 +46,29 @@ module Promiscuous
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
+
module ConsoleHelpers
|
50
|
+
# These are just for the subscriber, some helpers to debug in production
|
51
|
+
def global_key
|
52
|
+
Promiscuous::Redis.sub_key('global')
|
53
|
+
end
|
54
|
+
|
55
|
+
def global_version
|
56
|
+
Promiscuous::Redis.get(global_key).to_i
|
57
|
+
end
|
58
|
+
|
59
|
+
def global_version=(value)
|
60
|
+
Promiscuous::Redis.set(global_key, value)
|
61
|
+
Promiscuous::Redis.publish(global_key, value)
|
62
|
+
value
|
63
|
+
end
|
64
|
+
|
65
|
+
def global_version!
|
66
|
+
version = Promiscuous::Redis.incr(global_key)
|
67
|
+
Promiscuous::Redis.publish(global_key, version)
|
68
|
+
version
|
69
|
+
end
|
70
|
+
end
|
71
|
+
extend ConsoleHelpers
|
72
|
+
|
49
73
|
at_exit { self.disconnect rescue nil }
|
50
74
|
end
|
@@ -20,7 +20,9 @@ module Promiscuous::AMQP::RubyAMQP
|
|
20
20
|
end
|
21
21
|
|
22
22
|
connection = ::AMQP.connect(amqp_options)
|
23
|
-
self.channel = ::AMQP::Channel.new(connection,
|
23
|
+
self.channel = ::AMQP::Channel.new(connection,
|
24
|
+
:auto_recovery => true,
|
25
|
+
:prefetch => Promiscuous::Config.prefetch)
|
24
26
|
|
25
27
|
connection.on_tcp_connection_loss do |conn|
|
26
28
|
unless conn.reconnecting?
|
data/lib/promiscuous/cli.rb
CHANGED
@@ -51,13 +51,22 @@ class Promiscuous::CLI
|
|
51
51
|
opts.separator "Options:"
|
52
52
|
|
53
53
|
opts.on "-b", "--bareback", "Bareback mode aka no dependencies. Use with extreme caution" do
|
54
|
-
|
54
|
+
Promiscuous::Config.bareback = true
|
55
55
|
end
|
56
56
|
|
57
|
-
opts.on "-
|
57
|
+
opts.on "-l", "--require FILE", "File to require to load your app. Don't worry about it with rails" do |file|
|
58
58
|
options[:require] = file
|
59
59
|
end
|
60
60
|
|
61
|
+
opts.on "-r", "--recovery [TIMEOUT]", "Run in recovery mode. Defaults to 10 seconds before recovering" do |timeout|
|
62
|
+
Promiscuous::Config.recovery_timeout = (timeout || 10).to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on "-p", "--prefetch [NUM]", "Number of messages to prefetch" do |prefetch|
|
66
|
+
exit 1 if prefetch.to_i == 0
|
67
|
+
Promiscuous::Config.prefetch = prefetch.to_i
|
68
|
+
end
|
69
|
+
|
61
70
|
opts.on("-h", "--help", "Show this message") do
|
62
71
|
puts opts
|
63
72
|
exit
|
@@ -106,7 +115,7 @@ class Promiscuous::CLI
|
|
106
115
|
def boot
|
107
116
|
self.options = parse_args(ARGV)
|
108
117
|
load_app
|
109
|
-
|
118
|
+
show_bareback_warnings
|
110
119
|
run
|
111
120
|
end
|
112
121
|
|
@@ -117,9 +126,8 @@ class Promiscuous::CLI
|
|
117
126
|
end
|
118
127
|
end
|
119
128
|
|
120
|
-
def
|
121
|
-
if
|
122
|
-
Promiscuous::Config.bareback = true
|
129
|
+
def show_bareback_warnings
|
130
|
+
if Promiscuous::Config.bareback == true
|
123
131
|
print_status "WARNING: --- BAREBACK MODE ----"
|
124
132
|
print_status "WARNING: You are replicating without protection, you can get out of sync in no time"
|
125
133
|
print_status "WARNING: --- BAREBACK MODE ----"
|
data/lib/promiscuous/config.rb
CHANGED
@@ -1,20 +1,25 @@
|
|
1
1
|
module Promiscuous::Config
|
2
|
-
mattr_accessor :app, :logger, :error_notifier, :backend, :amqp_url,
|
2
|
+
mattr_accessor :app, :logger, :error_notifier, :backend, :amqp_url,
|
3
|
+
:redis_url, :queue_options, :heartbeat, :bareback,
|
4
|
+
:recovery_timeout, :prefetch
|
3
5
|
|
4
6
|
def self.backend=(value)
|
5
7
|
@@backend = value
|
6
8
|
Promiscuous::AMQP.backend = value unless value.nil?
|
7
9
|
end
|
8
10
|
|
9
|
-
def self.
|
11
|
+
def self.reset
|
10
12
|
class_variables.each { |var| class_variable_set(var, nil) }
|
13
|
+
end
|
11
14
|
|
15
|
+
def self.configure(&block)
|
12
16
|
block.call(self)
|
13
17
|
|
14
18
|
self.backend ||= defined?(EventMachine) && EventMachine.reactor_running? ? :rubyamqp : :bunny
|
15
19
|
self.logger ||= defined?(Rails) ? Rails.logger : Logger.new(STDERR).tap { |l| l.level = Logger::WARN }
|
16
20
|
self.queue_options ||= {:durable => true, :arguments => {'x-ha-policy' => 'all'}}
|
17
21
|
self.heartbeat ||= 60
|
22
|
+
self.prefetch ||= 1000
|
18
23
|
|
19
24
|
Promiscuous.connect
|
20
25
|
end
|
data/lib/promiscuous/error.rb
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
class Promiscuous::Error::Recover < RuntimeError; end
|
@@ -17,6 +17,7 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def connect
|
20
|
+
@queued_messages = 0
|
20
21
|
@subscriptions = {}
|
21
22
|
self.redis = Promiscuous::Redis.new_celluloid_connection
|
22
23
|
end
|
@@ -106,6 +107,8 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
106
107
|
# when calling worker.pump.start
|
107
108
|
return unless self.redis
|
108
109
|
|
110
|
+
bump_message_counter!
|
111
|
+
|
109
112
|
return process_message!(msg) unless msg.has_dependencies?
|
110
113
|
|
111
114
|
# The message synchronizer only takes care of happens before (>=) dependencies.
|
@@ -115,7 +118,76 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
115
118
|
end
|
116
119
|
end
|
117
120
|
|
121
|
+
def bump_message_counter!
|
122
|
+
@queued_messages += 1
|
123
|
+
maybe_recover
|
124
|
+
end
|
125
|
+
|
126
|
+
def maybe_recover
|
127
|
+
recovery_timeout = Promiscuous::Config.recovery_timeout
|
128
|
+
return unless recovery_timeout
|
129
|
+
|
130
|
+
reset_recovery_timer
|
131
|
+
if should_recover?
|
132
|
+
# We've reached the amount of messages the amqp queue is willing to give us.
|
133
|
+
# We also know that we are not processing messages (@queued_messages is
|
134
|
+
# decremented before we send the message to the runners).
|
135
|
+
|
136
|
+
Promiscuous.warn "[receive] Recovering in #{recovery_timeout} seconds..."
|
137
|
+
@recover_timer = after(recovery_timeout) { reset_recovery_timer; recover }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def reset_recovery_timer
|
142
|
+
@recover_timer.try(:reset)
|
143
|
+
@recover_timer = nil
|
144
|
+
end
|
145
|
+
|
146
|
+
def should_recover?
|
147
|
+
@queued_messages == Promiscuous::Config.prefetch
|
148
|
+
end
|
149
|
+
|
150
|
+
def recover
|
151
|
+
return unless should_recover?
|
152
|
+
|
153
|
+
global_key = Promiscuous::Redis.sub_key('global')
|
154
|
+
current_version = Promiscuous::Redis.get(global_key).to_i
|
155
|
+
|
156
|
+
global_callbacks = get_subscription(global_key).callbacks
|
157
|
+
expected_next_msg_version = global_callbacks.values.map(&:version).min
|
158
|
+
version_to_allow_progress = expected_next_msg_version - 1
|
159
|
+
|
160
|
+
num_messages_to_skip = version_to_allow_progress - current_version
|
161
|
+
|
162
|
+
if num_messages_to_skip > 0
|
163
|
+
recovery_msg = "Recovering. Moving current version from #{current_version} " +
|
164
|
+
"to #{version_to_allow_progress}. " +
|
165
|
+
"Skipping #{num_messages_to_skip} messages..."
|
166
|
+
else
|
167
|
+
recovery_msg = "Not recovering. current version is #{current_version}, " +
|
168
|
+
"while we just need #{version_to_allow_progress}. " +
|
169
|
+
"Offset is #{num_messages_to_skip} message."
|
170
|
+
end
|
171
|
+
|
172
|
+
e = Promiscuous::Error::Recover.new(recovery_msg)
|
173
|
+
if current_version > 0
|
174
|
+
Promiscuous.error "[receive] #{e}"
|
175
|
+
Promiscuous::Config.error_notifier.try(:call, e)
|
176
|
+
else
|
177
|
+
Promiscuous.info "[receive] #{e}"
|
178
|
+
# Initial sync, nothing to worry about
|
179
|
+
end
|
180
|
+
|
181
|
+
if num_messages_to_skip > 0
|
182
|
+
Promiscuous::Redis.set(global_key, version_to_allow_progress)
|
183
|
+
Promiscuous::Redis.publish(global_key, version_to_allow_progress)
|
184
|
+
end
|
185
|
+
ensure
|
186
|
+
reset_recovery_timer
|
187
|
+
end
|
188
|
+
|
118
189
|
def process_message!(msg)
|
190
|
+
@queued_messages -= 1
|
119
191
|
Celluloid::Actor[:runners].process!(msg)
|
120
192
|
end
|
121
193
|
|
@@ -136,7 +208,7 @@ class Promiscuous::Subscriber::Worker::MessageSynchronizer
|
|
136
208
|
end
|
137
209
|
|
138
210
|
class Subscription
|
139
|
-
attr_accessor :parent, :key
|
211
|
+
attr_accessor :parent, :key, :callbacks
|
140
212
|
|
141
213
|
def initialize(parent, key)
|
142
214
|
self.parent = parent
|
data/lib/promiscuous/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: promiscuous
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.51.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-02-
|
13
|
+
date: 2013-02-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -221,19 +221,20 @@ files:
|
|
221
221
|
- lib/promiscuous/error/subscriber.rb
|
222
222
|
- lib/promiscuous/error/publisher.rb
|
223
223
|
- lib/promiscuous/error/connection.rb
|
224
|
+
- lib/promiscuous/error/recover.rb
|
224
225
|
- lib/promiscuous/ephemeral.rb
|
225
226
|
- lib/promiscuous/autoload.rb
|
226
|
-
- lib/promiscuous/error.rb
|
227
227
|
- lib/promiscuous/loader.rb
|
228
228
|
- lib/promiscuous/railtie.rb
|
229
229
|
- lib/promiscuous/common.rb
|
230
230
|
- lib/promiscuous/publisher.rb
|
231
231
|
- lib/promiscuous/amqp.rb
|
232
232
|
- lib/promiscuous/subscriber.rb
|
233
|
-
- lib/promiscuous/config.rb
|
234
|
-
- lib/promiscuous/cli.rb
|
235
233
|
- lib/promiscuous/redis.rb
|
236
234
|
- lib/promiscuous/observer.rb
|
235
|
+
- lib/promiscuous/cli.rb
|
236
|
+
- lib/promiscuous/error.rb
|
237
|
+
- lib/promiscuous/config.rb
|
237
238
|
- lib/promiscuous/version.rb
|
238
239
|
- lib/promiscuous.rb
|
239
240
|
- bin/promiscuous
|