active_pubsub 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 732df7c0baced02169548ca0e1b68fe64672bf98
4
- data.tar.gz: dc0e9439ab43e368ebef496cb24a0686e1d6d7e1
3
+ metadata.gz: 1934c830b54ffd62b61a8854ba7014e7641a134d
4
+ data.tar.gz: cf1d897e9d8f5baf7ee7fb9e9f4ba99fd36fdb4d
5
5
  SHA512:
6
- metadata.gz: 1fa9d7aabee001f5a1423d590277d0a6de796d3220f1ffa8c884699343e02689a4fc17fb2b8ef7389446fe7f244aa4566dc306fd22cde720c537b5a94dcdb2e5
7
- data.tar.gz: f5068dc1ce77133ca6bbb2574d942be00a1c683c7b967da06465db2e1ecc44a1cedc4d2c78d1797c5762a9e1651ec8196e679ef3e865798c8d094657c1963fb6
6
+ metadata.gz: 6b764248afe7d0aae61d1709e3f6926a03ced904465c5719a5ab749e276722ef882a411cd50da0872aa44b2e11dbd831606ff84cd367eac809460a734b1d5150
7
+ data.tar.gz: 98ed111e12e4b56995e87ed710cbf23f4f20f0c567e137127065503456968cba2116e96b72ff7aaa2e53bf0681e3ad6588b00da35e7ef1f49eb9a79924a2bde5
data/README.md CHANGED
@@ -144,6 +144,31 @@ end
144
144
 
145
145
  Its still really early in development cycle, so there may be issues running tests if you aren't running rabbit. Should probably fix that.
146
146
 
147
+ ### Configuration, Persistence, Acknowledgement and Durability
148
+
149
+ Rabbit allows you to configure the hell out of it. In the spirit of convention over configuration, Ive attempted to dumb that down into shared settings, i.e., durability being applied across the board (to queues, exchanges, as well as persisting messages, set to true)
150
+
151
+ **NOTE**
152
+
153
+ If you change a config setting, you will likely need to remove your queues and exchanges. Rabbit does not let you override queues or exchanges or bindings at runtime with different settings. You need to destroy them manually, and easiest way to do this is via gui.
154
+
155
+ ** Durability **
156
+
157
+ ``` ruby
158
+ ::ActivePubsub.config.durable = true
159
+ ```
160
+
161
+ Will make all your queues, exchanges, durable. This means they will be there when your broker is restarted. It will ALSO make the publishing of messages persisted to disk. I could split this into two settings, but once again, in the spirit of simplicity Ive elected not to for now.
162
+
163
+
164
+ ** Message Acknowledgement **
165
+
166
+ ``` ruby
167
+ ::ActivePubsub.config.ack = true
168
+ ```
169
+
170
+ Will turn on message acknowledgement. What this means, is if there is an error in your subscriber and it fails to get to the end of your on :eventname block, it will not acknowledge that it was processed, and mark it as unacknowledged. This is a way to provide insight into failures, as well as reprocessing events, however its a poor mans solution at best. Reason being, once a subscriber attempts to process a message and fails, rabbit marks that the consumer attempted to do so, and rabbit will not let release the message back to the queue (if it did, you would suffer from potentially immediate and infinite retrys to process the message). See the following link for more details on the problem in general: http://grokbase.com/t/rabbitmq/rabbitmq-discuss/137ts15m5r/push-to-back-of-queue-on-nack
171
+
147
172
  ### Installation
148
173
 
149
174
  Add this line to your application's Gemfile:
@@ -9,6 +9,7 @@ require "active_attr"
9
9
  require "pry"
10
10
  require "active_pubsub/config"
11
11
  require "active_pubsub/logging"
12
+ require "active_pubsub/settings"
12
13
 
13
14
  module ActivePubsub
14
15
  class << self
@@ -26,6 +27,10 @@ module ActivePubsub
26
27
  ::ActiveSupport.run_load_hooks(:active_pubsub, self)
27
28
  end
28
29
 
30
+ def self.disable_publisher!
31
+ configuration.disable_publisher = true
32
+ end
33
+
29
34
  def self.load_subscribers
30
35
  ::Dir.glob(::Rails.root.join('app', 'subscribers', "*.rb")).each{ |file| load file }
31
36
  end
@@ -42,6 +47,10 @@ module ActivePubsub
42
47
  ::Celluloid::Actor[:rabbit_publisher]
43
48
  end
44
49
 
50
+ def self.publisher_disabled?
51
+ configuration.publisher_disabled
52
+ end
53
+
45
54
  def self.start_publisher
46
55
  ::ActivePubsub::Publisher.start unless ::ActivePubsub::Publisher.started?
47
56
  end
@@ -11,6 +11,9 @@ module ActivePubsub
11
11
  self[:publish_as] ||= nil
12
12
  self[:service_namespace] ||= nil
13
13
  self[:logger] ||= ::ActivePubsub::Logging.logger
14
+ self[:durable] ||= false
15
+ self[:ack] ||= false
16
+ self[:publisher_disabled] ||= false
14
17
  end
15
18
  end
16
19
  end
@@ -1,5 +1,6 @@
1
1
  module ActivePubsub
2
2
  class Publisher
3
+ include ::ActivePubsub::Settings
3
4
  include ::Celluloid
4
5
 
5
6
  attr_accessor :connection
@@ -50,11 +51,20 @@ module ActivePubsub
50
51
  @exchanges ||= {}
51
52
  end
52
53
 
54
+ def options_for_publish(event)
55
+ {
56
+ :routing_key => event.routing_key,
57
+ :persistent => ::ActivePubsub.config.durable
58
+ }
59
+ end
60
+
53
61
  def publish_event(event)
62
+ return if ::ActivePubsub.publisher_disabled?
63
+
54
64
  ::ActiveRecord::Base.connection_pool.with_connection do
55
65
  ::ActivePubsub.logger.info("Publishing event: #{event.id} to #{event.routing_key}")
56
66
 
57
- exchanges[event.exchange].publish(serialize_event(event), :routing_key => event.routing_key)
67
+ exchanges[event.exchange].publish(serialize_event(event), options_for_publish(event))
58
68
  end
59
69
  end
60
70
 
@@ -63,7 +73,7 @@ module ActivePubsub
63
73
  end
64
74
 
65
75
  def register_exchange(exchange_name)
66
- exchanges[exchange_name] ||= channel.topic(exchange_name, :auto_delete => true)
76
+ exchanges[exchange_name] ||= channel.topic(exchange_name, exchange_settings)
67
77
  end
68
78
  end
69
79
  end
@@ -0,0 +1,40 @@
1
+ module ActivePubsub
2
+ module Settings
3
+ extend ::ActiveSupport::Concern
4
+
5
+ def exchange_settings
6
+ self.class.exchange_settings
7
+ end
8
+
9
+ def queue_settings
10
+ self.class.queue_settings
11
+ end
12
+
13
+ def subscribe_settings
14
+ self.class.subscribe_settings
15
+ end
16
+
17
+ module ClassMethods
18
+ def exchange_settings
19
+ {
20
+ :durable => ::ActivePubsub.config.durable,
21
+ :auto_delete => !::ActivePubsub.config.durable
22
+ }
23
+ end
24
+
25
+ def queue_settings
26
+ {
27
+ :manual_ack => ::ActivePubsub.config.ack,
28
+ :durable => ::ActivePubsub.config.durable
29
+ }
30
+ end
31
+
32
+ def subscribe_settings
33
+ {
34
+ :manual_ack => ::ActivePubsub.config.ack,
35
+ :block => false
36
+ }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -2,6 +2,8 @@ require 'active_support/all'
2
2
 
3
3
  module ActivePubsub
4
4
  class Subscriber
5
+ include ::ActivePubsub::Settings
6
+
5
7
  attr_accessor :connection
6
8
 
7
9
  class_attribute :events
@@ -28,7 +30,7 @@ module ActivePubsub
28
30
  end
29
31
 
30
32
  def self.exchange
31
- channel.topic(exchange_name, :auto_delete => true)
33
+ channel.topic(exchange_name, exchange_settings)
32
34
  end
33
35
 
34
36
  def self.inherited(klass)
@@ -43,9 +45,9 @@ module ActivePubsub
43
45
  return if started?
44
46
 
45
47
  events.each_pair do |event_name, block|
46
- channel.queue(queue_for_event(event_name.to_s))
48
+ channel.queue(queue_for_event(event_name.to_s), queue_settings)
47
49
  .bind(exchange, :routing_key => routing_key_for_event(event_name))
48
- .subscribe do |delivery_info, properties, payload|
50
+ .subscribe(subscribe_settings) do |delivery_info, properties, payload|
49
51
  deserialized_event = deserialize_event(payload)
50
52
  deserialized_record = deserialize_record(deserialized_event[:record])
51
53
 
@@ -53,6 +55,8 @@ module ActivePubsub
53
55
  subscriber_instance.instance_exec(deserialized_record, &block)
54
56
 
55
57
  ::ActivePubsub.logger.info "#{delivery_info[:routing_key]} #{name} consumed #{deserialized_event}"
58
+
59
+ channel.ack(delivery_info.delivery_tag) if ::ActivePubsub.config.ack
56
60
  end
57
61
  end
58
62
 
@@ -1,3 +1,3 @@
1
1
  module ActivePubsub
2
- VERSION = "0.0.8"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -15,6 +15,10 @@ describe ::ActivePubsub::Config do
15
15
  its(:address) { should eq ENV["RABBITMQ_URL"] }
16
16
  its(:publish_as) { should eq nil }
17
17
  its(:service_namespace) { should eq nil }
18
+ its(:ack) { should be false }
19
+ its(:durable) { should be false }
20
+ its(:logger) { should be_instance_of(::Logger) }
21
+ its(:publisher_disabled) { should eq false }
18
22
  end
19
23
 
20
24
  end
@@ -46,6 +46,32 @@ describe ::ActivePubsub::Publisher do
46
46
  its(:exchanges) { should include(exchange_key) }
47
47
  end
48
48
 
49
+ describe "#options_for_publish" do
50
+ let(:expected) {
51
+ {
52
+ :routing_key => fake_event.routing_key,
53
+ :persistent => false
54
+ }
55
+ }
56
+
57
+ it { subject.options_for_publish(fake_event).should eq expected }
58
+
59
+ context "durable is true" do
60
+ before do
61
+ ::ActivePubsub::Config.any_instance.stub(:durable).and_return(true)
62
+ end
63
+
64
+ let(:expected) do
65
+ {
66
+ :routing_key => fake_event.routing_key,
67
+ :persistent => true
68
+ }
69
+ end
70
+
71
+ it { subject.options_for_publish(fake_event).should eq expected }
72
+ end
73
+ end
74
+
49
75
  describe "#publish_event" do
50
76
  it "should receive publish event with instance of event when publishable record is saved" do
51
77
  subject.should_receive(:publish_event).with(instance_of(::ActivePubsub::Event))
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe ::ActivePubsub::Settings do
4
+ subject {
5
+ class FakeSettingsIncluder
6
+ include ::ActivePubsub::Settings
7
+ end
8
+ }
9
+
10
+ its(:exchange_settings) {
11
+ options = { :durable => false, :auto_delete => true }
12
+ should eq options
13
+ }
14
+
15
+ its(:queue_settings) {
16
+ options = { :manual_ack => false, :durable => false }
17
+ should eq options
18
+ }
19
+
20
+ its(:subscribe_settings) {
21
+ options = { :manual_ack => false, :block => false }
22
+ should eq options
23
+ }
24
+
25
+ context "acknowledgement is true" do
26
+ before do
27
+ ::ActivePubsub::Config.any_instance.stub(:ack).and_return(true)
28
+ end
29
+
30
+ its(:queue_settings) {
31
+ options = { :manual_ack => true, :durable => false }
32
+ should eq options
33
+ }
34
+
35
+ its(:subscribe_settings) {
36
+ options = { :manual_ack => true, :block => false }
37
+ should eq options
38
+ }
39
+ end
40
+
41
+ context "durability is true" do
42
+ its(:exchange_settings) {
43
+ options = { :durable => false, :auto_delete => true }
44
+ should eq options
45
+ }
46
+
47
+ its(:queue_settings) {
48
+ options = { :manual_ack => false, :durable => false }
49
+ should eq options
50
+ }
51
+
52
+ its(:subscribe_settings) {
53
+ options = { :manual_ack => false, :block => false }
54
+ should eq options
55
+ }
56
+ end
57
+ end
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_pubsub
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Ayre
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-27 00:00:00.000000000 Z
11
+ date: 2014-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_attr
@@ -319,6 +319,7 @@ files:
319
319
  - lib/active_pubsub/publishable.rb
320
320
  - lib/active_pubsub/publisher.rb
321
321
  - lib/active_pubsub/railtie.rb
322
+ - lib/active_pubsub/settings.rb
322
323
  - lib/active_pubsub/subscribe_to_changes.rb
323
324
  - lib/active_pubsub/subscriber.rb
324
325
  - lib/active_pubsub/version.rb
@@ -327,6 +328,7 @@ files:
327
328
  - spec/active_pubsub/publish_with_serializer_spec.rb
328
329
  - spec/active_pubsub/publishable_spec.rb
329
330
  - spec/active_pubsub/publisher_spec.rb
331
+ - spec/active_pubsub/settings_spec.rb
330
332
  - spec/active_pubsub/subscribe_to_changes_spec.rb
331
333
  - spec/active_pubsub/subscriber_spec.rb
332
334
  - spec/spec_helper.rb
@@ -369,6 +371,7 @@ test_files:
369
371
  - spec/active_pubsub/publish_with_serializer_spec.rb
370
372
  - spec/active_pubsub/publishable_spec.rb
371
373
  - spec/active_pubsub/publisher_spec.rb
374
+ - spec/active_pubsub/settings_spec.rb
372
375
  - spec/active_pubsub/subscribe_to_changes_spec.rb
373
376
  - spec/active_pubsub/subscriber_spec.rb
374
377
  - spec/spec_helper.rb