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 +4 -4
- data/README.md +25 -0
- data/lib/active_pubsub.rb +9 -0
- data/lib/active_pubsub/config.rb +3 -0
- data/lib/active_pubsub/publisher.rb +12 -2
- data/lib/active_pubsub/settings.rb +40 -0
- data/lib/active_pubsub/subscriber.rb +7 -3
- data/lib/active_pubsub/version.rb +1 -1
- data/spec/active_pubsub/config_spec.rb +4 -0
- data/spec/active_pubsub/publisher_spec.rb +26 -0
- data/spec/active_pubsub/settings_spec.rb +57 -0
- data/spec/test.db +0 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1934c830b54ffd62b61a8854ba7014e7641a134d
|
4
|
+
data.tar.gz: cf1d897e9d8f5baf7ee7fb9e9f4ba99fd36fdb4d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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:
|
data/lib/active_pubsub.rb
CHANGED
@@ -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
|
data/lib/active_pubsub/config.rb
CHANGED
@@ -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),
|
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,
|
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,
|
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
|
|
@@ -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
|
data/spec/test.db
CHANGED
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.
|
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-
|
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
|