promiscuous 0.19.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,11 +21,37 @@ module Promiscuous
21
21
  end
22
22
 
23
23
  connection = ::AMQP.connect(amqp_options)
24
- self.channel = ::AMQP::Channel.new(connection)
24
+ self.channel = ::AMQP::Channel.new(connection, :auto_recovery => true)
25
+
26
+ connection.on_tcp_connection_loss do |conn|
27
+ unless conn.reconnecting?
28
+ Promiscuous.warn "[connection] Lost connection. Reconnecting..."
29
+ conn.periodically_reconnect(2)
30
+
31
+ exception = StandardError.new 'Lost connection'
32
+ Promiscuous::Config.error_handler.try(:call, exception)
33
+
34
+ Promiscuous::Worker.pause # TODO XXX This doesn't belong here
35
+ end
36
+ end
37
+
38
+ connection.on_recovery do |conn|
39
+ Promiscuous.warn "[connection] Reconnected"
40
+ Promiscuous::Worker.resume # TODO XXX This doesn't belong here
41
+ end
42
+
43
+ connection.on_error do |conn, conn_close|
44
+ # No need to handle CONNECTION_FORCED since on_tcp_connection_loss takes
45
+ # care of it.
46
+ Promiscuous.warn "[connection] #{conn_close.reply_text}"
47
+ end
25
48
  end
26
49
 
27
50
  def self.disconnect
28
- self.channel.close if self.channel
51
+ if self.channel && self.channel.connection.connected?
52
+ self.channel.connection.close
53
+ self.channel.close
54
+ end
29
55
  self.channel = nil
30
56
  end
31
57
 
@@ -42,7 +68,14 @@ module Promiscuous
42
68
  end
43
69
 
44
70
  def self.publish(options={})
45
- Promiscuous.info "[publish] (#{options[:exchange_name]}) #{options[:key]} -> #{options[:payload]}"
71
+ info_msg = "(#{options[:exchange_name]}) #{options[:key]} -> #{options[:payload]}"
72
+
73
+ unless channel.connection.connected?
74
+ exception = StandardError.new 'Lost connection'
75
+ raise Promiscuous::Publisher::Error.new(exception, info_msg)
76
+ end
77
+
78
+ Promiscuous.info "[publish] #{info_msg}"
46
79
  exchange(options[:exchange_name]).
47
80
  publish(options[:payload], :routing_key => options[:key], :persistent => true)
48
81
  end
@@ -24,6 +24,7 @@ class Promiscuous::CLI
24
24
  Signal.trap(signal) do
25
25
  print_status "Exiting..."
26
26
  Promiscuous::Worker.stop
27
+ Promiscuous::AMQP.disconnect
27
28
  EM.stop
28
29
  end
29
30
  end
@@ -1,6 +1,8 @@
1
1
  class Promiscuous::Publisher::Worker
2
2
  include Promiscuous::Common::Worker
3
3
 
4
+ attr_accessor :recovered
5
+
4
6
  def self.poll_delay
5
7
  # TODO Configurable globally
6
8
  # TODO Configurable per publisher
@@ -17,8 +19,7 @@ class Promiscuous::Publisher::Worker
17
19
 
18
20
  def replicate
19
21
  check_indexes
20
- EM.defer proc { self.replicate_once },
21
- proc { EM::Timer.new(self.class.poll_delay) { replicate } }
22
+ EM::PeriodicTimer.new(self.class.poll_delay) { self.replicate_once }
22
23
  end
23
24
 
24
25
  def replicate_once
@@ -35,25 +36,50 @@ class Promiscuous::Publisher::Worker
35
36
  unless e.is_a?(Promiscuous::Publisher::Error)
36
37
  e = Promiscuous::Publisher::Error.new(e, nil)
37
38
  end
38
- Promiscuous.error "[publish] FATAL #{e} #{e.backtrace}"
39
+
40
+ if self.recovered
41
+ Promiscuous.warn "[publish] will retry #{e.instance.try(:id)} #{e} #{e.backtrace}"
42
+ else
43
+ Promiscuous.error "[publish] FATAL #{e.instance.try(:id)} #{e} #{e.backtrace}"
44
+ end
45
+
39
46
  Promiscuous::Config.error_handler.try(:call, e)
40
47
  end
41
48
  end
42
49
 
43
50
  def replicate_collection(klass)
44
- return if self.stop
45
- # TODO Check for indexes and if not there, bail out
46
- while instance = klass.where(:_psp => true).find_and_modify(
47
- {'$unset' => {:_psp => 1}}, :bypass_promiscuous => true)
51
+ loop do
52
+ break if self.stop
53
+
54
+ self.recovered = false
55
+ instance = klass.where(:_psp => true).
56
+ find_and_modify({'$unset' => {:_psp => 1}}, :bypass_promiscuous => true)
57
+ break unless instance
58
+
48
59
  replicate_instance(instance)
49
60
  end
50
61
  end
51
62
 
52
63
  def replicate_instance(instance)
53
- return if self.stop
54
64
  instance.promiscuous_sync
55
65
  rescue Exception => e
56
- # TODO set back the psp field
57
- raise Promiscuous::Publisher::Error.new(e, instance)
66
+ # We failed publishing. Best effort recover.
67
+ if e.is_a?(Promiscuous::Publisher::Error)
68
+ e.instance = instance
69
+ else
70
+ e = Promiscuous::Publisher::Error.new(e, instance)
71
+ end
72
+
73
+ begin
74
+ # The following update will set the _psp flag to true again, effectively
75
+ # requeuing the publish action.
76
+ instance.class.where(instance.atomic_selector).update({})
77
+ self.recovered = true
78
+ rescue
79
+ # Swallow exception of a failed recovery, the log file will have a FATAL entry.
80
+ # The user needs to manually resync.
81
+ end
82
+
83
+ raise e
58
84
  end
59
85
  end
@@ -1,3 +1,3 @@
1
1
  module Promiscuous
2
- VERSION = '0.19.0'
2
+ VERSION = '0.20.0'
3
3
  end
@@ -15,4 +15,12 @@ module Promiscuous::Worker
15
15
  self.workers.each { |w| w.stop = true }
16
16
  self.workers.clear
17
17
  end
18
+
19
+ def self.pause
20
+ self.workers.each { |w| w.stop = true }
21
+ end
22
+
23
+ def self.resume
24
+ self.workers.each { |w| w.stop = false }
25
+ end
18
26
  end
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.19.0
4
+ version: 0.20.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: 2012-12-20 00:00:00.000000000 Z
13
+ date: 2013-01-04 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -117,68 +117,68 @@ executables:
117
117
  extensions: []
118
118
  extra_rdoc_files: []
119
119
  files:
120
- - lib/promiscuous/amqp/bunny.rb
121
120
  - lib/promiscuous/amqp/null.rb
121
+ - lib/promiscuous/amqp/bunny.rb
122
122
  - lib/promiscuous/amqp/rubyamqp.rb
123
- - lib/promiscuous/common.rb
124
- - lib/promiscuous/common/class_helpers.rb
125
123
  - lib/promiscuous/common/lint.rb
126
124
  - lib/promiscuous/common/lint/base.rb
125
+ - lib/promiscuous/common/class_helpers.rb
127
126
  - lib/promiscuous/common/options.rb
128
127
  - lib/promiscuous/common/worker.rb
129
- - lib/promiscuous/config.rb
130
128
  - lib/promiscuous/loader.rb
131
- - lib/promiscuous/observer.rb
132
- - lib/promiscuous/publisher.rb
133
- - lib/promiscuous/publisher/active_record.rb
134
129
  - lib/promiscuous/publisher/envelope.rb
135
- - lib/promiscuous/publisher/ephemeral.rb
136
- - lib/promiscuous/publisher/error.rb
137
130
  - lib/promiscuous/publisher/lint.rb
138
131
  - lib/promiscuous/publisher/lint/amqp.rb
139
132
  - lib/promiscuous/publisher/lint/attributes.rb
140
133
  - lib/promiscuous/publisher/lint/base.rb
141
134
  - lib/promiscuous/publisher/lint/class.rb
142
135
  - lib/promiscuous/publisher/lint/polymorphic.rb
143
- - lib/promiscuous/publisher/mock.rb
144
136
  - lib/promiscuous/publisher/mongoid/embedded.rb
145
137
  - lib/promiscuous/publisher/mongoid/defer_embedded.rb
146
138
  - lib/promiscuous/publisher/mongoid/embedded_many.rb
147
139
  - lib/promiscuous/publisher/mongoid/defer.rb
148
140
  - lib/promiscuous/publisher/polymorphic.rb
141
+ - lib/promiscuous/publisher/mock.rb
149
142
  - lib/promiscuous/publisher/attributes.rb
150
143
  - lib/promiscuous/publisher/amqp.rb
144
+ - lib/promiscuous/publisher/model.rb
145
+ - lib/promiscuous/publisher/active_record.rb
151
146
  - lib/promiscuous/publisher/base.rb
152
- - lib/promiscuous/publisher/mongoid.rb
153
147
  - lib/promiscuous/publisher/class.rb
154
- - lib/promiscuous/publisher/model.rb
148
+ - lib/promiscuous/publisher/ephemeral.rb
149
+ - lib/promiscuous/publisher/mongoid.rb
150
+ - lib/promiscuous/publisher/error.rb
155
151
  - lib/promiscuous/publisher/worker.rb
156
152
  - lib/promiscuous/subscriber/active_record.rb
157
153
  - lib/promiscuous/subscriber/envelope.rb
158
154
  - lib/promiscuous/subscriber/error.rb
159
155
  - lib/promiscuous/subscriber/lint.rb
160
156
  - lib/promiscuous/subscriber/lint/amqp.rb
161
- - lib/promiscuous/subscriber/lint/attributes.rb
162
157
  - lib/promiscuous/subscriber/lint/base.rb
163
158
  - lib/promiscuous/subscriber/lint/class.rb
164
159
  - lib/promiscuous/subscriber/lint/polymorphic.rb
165
- - lib/promiscuous/subscriber/mongoid/embedded.rb
160
+ - lib/promiscuous/subscriber/lint/attributes.rb
166
161
  - lib/promiscuous/subscriber/mongoid/embedded_many.rb
162
+ - lib/promiscuous/subscriber/mongoid/embedded.rb
167
163
  - lib/promiscuous/subscriber/mongoid/versioning.rb
164
+ - lib/promiscuous/subscriber/upsert.rb
168
165
  - lib/promiscuous/subscriber/observer.rb
169
166
  - lib/promiscuous/subscriber/polymorphic.rb
170
- - lib/promiscuous/subscriber/upsert.rb
171
167
  - lib/promiscuous/subscriber/amqp.rb
172
168
  - lib/promiscuous/subscriber/attributes.rb
173
- - lib/promiscuous/subscriber/base.rb
174
169
  - lib/promiscuous/subscriber/model.rb
170
+ - lib/promiscuous/subscriber/base.rb
175
171
  - lib/promiscuous/subscriber/class.rb
176
172
  - lib/promiscuous/subscriber/mongoid.rb
177
173
  - lib/promiscuous/subscriber/worker.rb
178
- - lib/promiscuous/subscriber.rb
179
- - lib/promiscuous/ephemeral.rb
174
+ - lib/promiscuous/observer.rb
175
+ - lib/promiscuous/common.rb
180
176
  - lib/promiscuous/amqp.rb
177
+ - lib/promiscuous/ephemeral.rb
178
+ - lib/promiscuous/subscriber.rb
179
+ - lib/promiscuous/publisher.rb
181
180
  - lib/promiscuous/railtie.rb
181
+ - lib/promiscuous/config.rb
182
182
  - lib/promiscuous/worker.rb
183
183
  - lib/promiscuous/cli.rb
184
184
  - lib/promiscuous/version.rb