promiscuous 0.19.0 → 0.20.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.
@@ -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