active_pubsub 0.0.2 → 0.0.3
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.
- checksums.yaml +4 -4
- data/README.md +98 -4
- data/active_pubsub.gemspec +1 -1
- data/bin/subscriber +7 -3
- data/lib/active_pubsub.rb +0 -1
- data/lib/active_pubsub/publisher.rb +0 -4
- data/lib/active_pubsub/railtie.rb +2 -3
- data/lib/active_pubsub/subscriber.rb +14 -5
- data/lib/active_pubsub/version.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6d67467176a0be6bf12783385e9ccb215a61b9d
|
4
|
+
data.tar.gz: dbef4a7b649425c4d1326f982970366f1ec297ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0217c66e7d33a9acbb750c1c66617819431baf28033a5c2b373449172172ad2ceb88fe91b198a939b951e25454e9cf928079cf1b7f6d4dfc6351dcaeb966b658
|
7
|
+
data.tar.gz: d64f92f24b55f9cb09336b96b00fc98d681ac54b7c859b6a945b2632df33fc1bb3499c581b01d03533b334d709df3d656c083c9cfaa46eee62751a2065876d6d
|
data/README.md
CHANGED
@@ -1,8 +1,104 @@
|
|
1
1
|
# ActivePubsub
|
2
2
|
|
3
|
-
|
3
|
+
Service oriented observers for active record, via RabbitMQ and Bunny gem. Publish/Observe changes made to ActiveRecord models asynchronously, from different applications/services.
|
4
4
|
|
5
|
-
|
5
|
+
Best examples can be found here:
|
6
|
+
https://github.com/jasonayre/active_pubsub_examples
|
7
|
+
|
8
|
+
## Publisher Example
|
9
|
+
``` ruby
|
10
|
+
class Post < ::ActiveRecord::Base
|
11
|
+
include ::ActivePubsub::Publishable
|
12
|
+
|
13
|
+
# This is the namespace for the local service
|
14
|
+
# The following Will set up a cms.post rabbit exchange
|
15
|
+
publish_as "cms"
|
16
|
+
end
|
17
|
+
```
|
18
|
+
|
19
|
+
## Subscriber example
|
20
|
+
``` ruby
|
21
|
+
# this is an example of a service that wants to do something when posts are created,
|
22
|
+
# updated, or destroyed, in the publishing service
|
23
|
+
|
24
|
+
class PostSubscriber < ::ActivePubsub::Subscriber
|
25
|
+
observes "cms"
|
26
|
+
as "aggregator"
|
27
|
+
|
28
|
+
on :created do |record|
|
29
|
+
puts record.inspect
|
30
|
+
end
|
31
|
+
|
32
|
+
on :destroyed do |record|
|
33
|
+
puts record.inspect
|
34
|
+
end
|
35
|
+
|
36
|
+
on :updated do |record|
|
37
|
+
puts record.inspect
|
38
|
+
end
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
## Publishing events
|
43
|
+
|
44
|
+
Just include ::ActivePubsub::Publishable module into an active record class whose events you want to publish.
|
45
|
+
|
46
|
+
``` ruby
|
47
|
+
class Post < ::ActiveRecord::Base
|
48
|
+
include ::ActivePubsub::Publishable
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
52
|
+
Also, you need to declare a namespace to publish under, either in the main configuration or in the model
|
53
|
+
|
54
|
+
``` ruby
|
55
|
+
class Post < ::ActiveRecord::Base
|
56
|
+
include ::ActivePubsub::Publishable
|
57
|
+
publish_as "cms"
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
Or in initializer
|
62
|
+
|
63
|
+
``` ruby
|
64
|
+
::ActivePubsub.configure do |config|
|
65
|
+
config.publish_as = "cms"
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
**IMPORTANT:** If you don't do one of the above the publisher will not be started.
|
70
|
+
|
71
|
+
The publisher simply runs in a new thread alongside your main application, connects to rabbit, and publishes the events.
|
72
|
+
|
73
|
+
## Subscribing to Events
|
74
|
+
|
75
|
+
Subscriber runs in a separate process from your application itself. You can start the subscriber with:
|
76
|
+
|
77
|
+
## Starting the subscriber
|
78
|
+
|
79
|
+
```
|
80
|
+
bundle exec subscriber start
|
81
|
+
```
|
82
|
+
|
83
|
+
## Benchmarks/Performance
|
84
|
+
|
85
|
+
No full benchmarks, but here are the results Ive seen so far via rabbit. MacbookPro, 2.6 i7 w 16gb ram. Running one publisher app and one subscriber, via examples at https://github.com/jasonayre/active_pubsub_examples
|
86
|
+
|
87
|
+
### Celluloid version > 0.16
|
88
|
+
|
89
|
+
I removed the gem lock to be compatibile with the most recent version of sidekiq which uses celluloid (0.15.2) or something, however I noticed a significant speed boost with > 0.16 version of celluloid.
|
90
|
+
|
91
|
+
Range of published messages/second: 250-500
|
92
|
+
Range processed (subscriber) messages/second: 250-500
|
93
|
+
|
94
|
+
### Celluloid version 15.2
|
95
|
+
|
96
|
+
Average published messages/second: 100-150
|
97
|
+
Average processed (subscriber) messages/second: 100-150
|
98
|
+
|
99
|
+
The throughput seems to be limited by the publisher mostly, from the very limited benchmarks thus far.
|
100
|
+
|
101
|
+
### Installation
|
6
102
|
|
7
103
|
Add this line to your application's Gemfile:
|
8
104
|
|
@@ -16,9 +112,7 @@ Or install it yourself as:
|
|
16
112
|
|
17
113
|
$ gem install active_pubsub
|
18
114
|
|
19
|
-
## Usage
|
20
115
|
|
21
|
-
TODO: Write usage instructions here
|
22
116
|
|
23
117
|
## Contributing
|
24
118
|
|
data/active_pubsub.gemspec
CHANGED
data/bin/subscriber
CHANGED
@@ -5,18 +5,22 @@ require 'active_pubsub'
|
|
5
5
|
require './config/environment.rb'
|
6
6
|
|
7
7
|
class Subscriber < ::Thor
|
8
|
-
desc "start", "Start
|
8
|
+
desc "start", "Start ActivePubsub Subscriber"
|
9
9
|
def start
|
10
|
-
puts "Starting
|
10
|
+
puts "Starting ActivePubsub Subscriber"
|
11
11
|
|
12
12
|
::ActivePubsub.load_subscribers
|
13
13
|
|
14
14
|
::ActivePubsub.start_subscribers
|
15
|
-
|
15
|
+
|
16
16
|
puts "Subscribers Started"
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
#todo: write event loop that handles shutdown gracefully
|
21
|
+
#however, it seems that Bunny knows when to wake subscribers up
|
22
|
+
#so sleeping seems to be enough for now
|
23
|
+
|
20
24
|
::Subscriber.start
|
21
25
|
|
22
26
|
sleep
|
data/lib/active_pubsub.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
'celluloid/io'
|
2
|
-
|
3
1
|
module ActivePubsub
|
4
2
|
class Publisher
|
5
3
|
include ::Celluloid
|
@@ -54,8 +52,6 @@ module ActivePubsub
|
|
54
52
|
|
55
53
|
def publish_event(event)
|
56
54
|
::ActiveRecord::Base.connection_pool.with_connection do
|
57
|
-
puts event.inspect
|
58
|
-
|
59
55
|
exchanges[event.exchange].publish(serialize_event(event), :routing_key => event.routing_key)
|
60
56
|
end
|
61
57
|
end
|
@@ -4,14 +4,13 @@ module ActivePubsub
|
|
4
4
|
class Railtie < ::Rails::Railtie
|
5
5
|
# we only need publisher started if service has a publishable model
|
6
6
|
::ActiveSupport.on_load(:active_record) do
|
7
|
-
puts "Active Record LOADED"
|
8
|
-
|
9
7
|
if(::ActivePubsub::Publisher.publishable_model_count > 0) && !::ActivePubsub::Publisher.started?
|
8
|
+
puts "Starting Publisher"
|
10
9
|
::ActivePubsub::Publisher.start
|
11
10
|
end
|
12
11
|
end
|
13
12
|
|
14
|
-
#todo: make
|
13
|
+
#todo: make this do something or remove it
|
15
14
|
def self.load_config_yml
|
16
15
|
config_file = ::YAML.load_file(config_yml_filepath)
|
17
16
|
return unless config_file.is_a?(Hash)
|
@@ -34,20 +34,21 @@ module ActivePubsub
|
|
34
34
|
channel.queue(queue_for_event(event_name.to_s))
|
35
35
|
.bind(exchange, :routing_key => routing_key_for_event(event_name))
|
36
36
|
.subscribe do |delivery_info, properties, payload|
|
37
|
-
|
38
|
-
|
37
|
+
deserialized_event = deserialize_event(payload)
|
38
|
+
deserialized_record = deserialize_record(deserialized_event[:record])
|
39
39
|
|
40
|
-
|
40
|
+
subscriber_instance = new(deserialized_record)
|
41
|
+
subscriber_instance.instance_exec(deserialized_record, &block)
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
46
|
def self.deserialize_event(event)
|
46
|
-
@current_event = Marshal.load(event)
|
47
|
+
@current_event = ::Marshal.load(event)
|
47
48
|
end
|
48
49
|
|
49
50
|
def self.deserialize_record(record)
|
50
|
-
@current_record = Marshal.load(record)
|
51
|
+
@current_record = ::Marshal.load(record)
|
51
52
|
end
|
52
53
|
|
53
54
|
def self.observes(target_exchange)
|
@@ -72,5 +73,13 @@ module ActivePubsub
|
|
72
73
|
|
73
74
|
puts message
|
74
75
|
end
|
76
|
+
|
77
|
+
### Instance Methods ###
|
78
|
+
attr_accessor :record
|
79
|
+
|
80
|
+
def initialize(record)
|
81
|
+
@record = record
|
82
|
+
end
|
83
|
+
|
75
84
|
end
|
76
85
|
end
|
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.3
|
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-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_attr
|
@@ -25,19 +25,19 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name: celluloid
|
28
|
+
name: celluloid
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 0.15.2
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 0.15.2
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: json
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|