mantle 2.0.0 → 2.0.1

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: 9faf822274115317d82c5b0e254b7551df79b3f5
4
- data.tar.gz: 2f9d06db2359478ca001df1b124eae4a46f84511
3
+ metadata.gz: 51daa43f7ab8c8a6c1b285092b2bec67b2ebc719
4
+ data.tar.gz: 8e45e8def173bd53d1ab532e76a4587d6487b304
5
5
  SHA512:
6
- metadata.gz: 8aa2b4e2059be5955e1f3cf033e0a775db5ffc29fb54947887a709024f9bc8e774ffc00b23d8fc9071685cbaff906b80459ce4908244efd873b981f36703a63f
7
- data.tar.gz: 946357abc8c54760e04b0b94f2f66c0238279181fa1b7cda362ae294a20bbf799104079662ef282e9ed6e5ba81aad2a73d600ebe0feefac7aaf13200e7106ad0
6
+ metadata.gz: 20d6e42054ffaa76766efc3e72ee186d750be5526fc5584c22d5ae5dc278166cc9370efa8e2419afcfb168a7fe112f0256dc24eea6981de881107bb0ef8cfd48
7
+ data.tar.gz: 5b45d490e2c750fc56a6627aeadbebabdd1f1c8464ab286fe461e854a652f7d9e8839f0905fde09e1a11f72e2243b94156d6943f87ee22b7468bda2a580d1037
data/README.md CHANGED
@@ -17,12 +17,12 @@ Setup a Rails initializer(`config/initializers/mantle.rb`):
17
17
 
18
18
 
19
19
  ```Ruby
20
- require_relative '../../app/models/mantle_message_handler'
21
-
22
20
  Mantle.configure do |config|
23
- config.message_bus_channels = %w[account:update orders]
24
21
  config.message_bus_redis = Redis.new(host: ENV["MESSAGE_BUS_REDIS_URL"] || 'localhost')
25
- config.message_handler = MantleMessageHandler
22
+ config.message_handlers = {
23
+ 'account:update' => 'MyMessageHandler',
24
+ 'order' => ['MyMessageHandler', 'MyOtherMessageHandler']
25
+ }
26
26
  end
27
27
  ```
28
28
 
@@ -30,11 +30,10 @@ The config takes a number of options, many of which have defaults:
30
30
 
31
31
  ```Ruby
32
32
  Mantle.configure do |config|
33
- config.message_bus_channels = ['deal:update', 'create:person'] # default: []
34
33
  config.message_bus_redis = Redis.new(host: 'localhost') # default: localhost
35
- config.message_handler = MyMessageHandler # requires implementation
36
34
  config.logger = Rails.logger # default: Logger.new(STDOUT)
37
35
  config.redis_namespace = "my-namespace" # default: no namespace
36
+ config.message_handlers = {'deal:update' => 'MyHandler'} # default: {}
38
37
  end
39
38
  ```
40
39
 
@@ -1,9 +1,9 @@
1
1
  # require 'sidekiq-pro'
2
- require_relative '../../app/models/mantle_message_handler'
3
2
 
4
3
  Mantle.configure do |config|
5
- config.message_bus_channels = %w[]
6
- config.message_bus_redis = Redis.new(host: ENV["MESSAGE_BUS_REDIS_URL"] || 'localhost')
7
- config.message_handler = MantleMessageHandler
4
+ config.message_bus_redis = Redis.new(
5
+ host: ENV.fetch('MESSAGE_BUS_REDIS_URL', 'localhost')
6
+ )
7
+ config.message_handlers = {}
8
8
  end
9
9
 
@@ -12,11 +12,14 @@ require_relative 'mantle/catch_up'
12
12
  require_relative 'mantle/configuration'
13
13
  require_relative 'mantle/error'
14
14
  require_relative 'mantle/local_redis'
15
+ require_relative 'mantle/logger'
15
16
  require_relative 'mantle/message'
16
17
  require_relative 'mantle/message_bus'
17
18
  require_relative 'mantle/message_handler'
19
+ require_relative 'mantle/message_handlers'
18
20
  require_relative 'mantle/message_router'
19
21
  require_relative 'mantle/workers/catch_up_cleanup_worker'
22
+ require_relative 'mantle/workers/message_handler_worker'
20
23
  require_relative 'mantle/workers/process_worker'
21
24
  require_relative 'mantle/version'
22
25
 
@@ -29,14 +32,18 @@ module Mantle
29
32
 
30
33
  def self.configure
31
34
  self.configuration ||= Configuration.new
32
- yield(configuration) if block_given?
35
+ yield configuration if block_given?
33
36
  end
34
37
 
35
38
  def self.receive_message(channel, message)
36
39
  Mantle.logger.debug("Message received on channel: #{channel}")
37
40
  Mantle.logger.debug("Mantle message: #{message}")
38
41
 
39
- self.configuration.message_handler.receive(channel, message)
42
+ self.configuration.message_handlers.receive_message channel, message
43
+ end
44
+
45
+ def self.channels
46
+ configuration.message_handlers.channels
40
47
  end
41
48
 
42
49
  def self.logger
@@ -9,7 +9,7 @@ module Mantle
9
9
 
10
10
  def initialize
11
11
  @redis = Mantle.configuration.message_bus_redis
12
- @message_bus_channels = Mantle.configuration.message_bus_channels
12
+ @message_bus_channels = Mantle.channels
13
13
  @key = KEY
14
14
  end
15
15
 
@@ -32,7 +32,7 @@ module Mantle
32
32
 
33
33
  def clear_expired
34
34
  max_time_to_clear = hours_ago_in_seconds(HOURS_TO_KEEP)
35
- redis.zremrangebyscore(key, 0 , max_time_to_clear)
35
+ redis.zremrangebyscore(key, 0, max_time_to_clear)
36
36
  end
37
37
 
38
38
  def catch_up
@@ -65,8 +65,7 @@ module Mantle
65
65
  end
66
66
 
67
67
  def deserialize_payload(payload)
68
- res = JSON.parse(payload)
69
- [res.fetch("channel"), res.fetch("message")]
68
+ JSON(payload).values_at 'channel', 'message'
70
69
  end
71
70
 
72
71
  def hours_ago_in_seconds(hours)
@@ -77,8 +76,7 @@ module Mantle
77
76
  private
78
77
 
79
78
  def serialize_payload(channel, message)
80
- payload = { channel: channel, message: message }
81
- JSON.generate(payload)
79
+ JSON({channel: channel, message: message})
82
80
  end
83
81
  end
84
82
  end
@@ -40,11 +40,9 @@ module Mantle
40
40
  end
41
41
 
42
42
  def load_config
43
- if options[:config]
44
- require File.expand_path(options[:config])
45
- else
46
- require File.expand_path("./config/initializers/mantle")
47
- end
43
+ require File.expand_path(
44
+ options.fetch :config, './config/initializers/mantle'
45
+ )
48
46
  end
49
47
 
50
48
  def configure_sidekiq
@@ -1,27 +1,19 @@
1
- require 'logger'
2
-
3
1
  module Mantle
4
2
  class Configuration
3
+ attr_accessor :message_bus_redis,
4
+ :logger,
5
+ :redis_namespace
5
6
 
6
- attr_accessor :message_bus_channels,
7
- :message_bus_redis,
8
- :message_handler,
9
- :logger,
10
- :redis_namespace
7
+ attr_reader :message_handlers
11
8
 
12
9
  def initialize
13
- @message_bus_channels = []
14
- @message_handler = Mantle::MessageHandler
15
- @logger = default_logger
10
+ @message_handlers = Mantle::MessageHandlers.new
11
+ @logger = Logger.new
16
12
  @redis_namespace = nil
17
13
  end
18
14
 
19
- private
20
-
21
- def default_logger
22
- logger = Logger.new(STDOUT)
23
- logger.level = Logger::INFO
24
- logger
15
+ def message_handlers=(hash_instance)
16
+ @message_handlers = Mantle::MessageHandlers.new(hash_instance)
25
17
  end
26
18
  end
27
19
  end
@@ -1,6 +1,11 @@
1
1
  module Mantle
2
- module Error
3
- MissingRedisConnection = Class.new(StandardError)
4
- MissingImplementation = Class.new(StandardError)
2
+ class Error < StandardError
3
+ MissingRedisConnection = Class.new(Error)
4
+
5
+ class MissingImplementation < Error
6
+ def message
7
+ "Implement self.receive(channel, object) and assign class to the message handler"
8
+ end
9
+ end
5
10
  end
6
11
  end
@@ -0,0 +1,11 @@
1
+ require 'logger'
2
+
3
+ module Mantle
4
+ class Logger < Logger
5
+ def initialize
6
+ super STDOUT
7
+ self.level = Logger::INFO
8
+ self
9
+ end
10
+ end
11
+ end
@@ -4,7 +4,6 @@ module Mantle
4
4
 
5
5
  def initialize
6
6
  @redis = Mantle.configuration.message_bus_redis
7
- @channels = Mantle.configuration.message_bus_channels
8
7
  end
9
8
 
10
9
  def publish(channel, message)
@@ -27,9 +26,13 @@ module Mantle
27
26
  def subscribe_to_channels
28
27
  raise Mantle::Error::MissingRedisConnection unless redis
29
28
 
30
- Mantle.logger.info("Subscribing to message bus for #{channels} ")
29
+ if Mantle.channels.any?
30
+ Mantle.logger.info("Subscribing to message bus for #{Mantle.channels} ")
31
+ else
32
+ Mantle.logger.info("No channels configured for subscription. Configure 'message_handlers' if this was unintentional.") and return
33
+ end
31
34
 
32
- redis.subscribe(channels) do |on|
35
+ redis.subscribe(Mantle.channels) do |on|
33
36
  on.message do |channel, json_message|
34
37
  message = JSON.parse(json_message)
35
38
  Mantle::MessageRouter.new(channel, message).route
@@ -39,6 +42,6 @@ module Mantle
39
42
 
40
43
  private
41
44
 
42
- attr_reader :redis, :channels
45
+ attr_reader :redis
43
46
  end
44
47
  end
@@ -1,7 +1,7 @@
1
1
  module Mantle
2
2
  class MessageHandler
3
3
  def self.receive(channel, message)
4
- raise Mantle::Error::MissingImplementation.new("Implement self.receive(channel, object) and assign class to the message handler")
4
+ raise Mantle::Error::MissingImplementation
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,19 @@
1
+ module Mantle
2
+ class MessageHandlers < SimpleDelegator
3
+ def initialize(hash_instance = {})
4
+ super hash_instance
5
+ end
6
+
7
+ def receive_message(channel, message)
8
+ Array(fetch(channel)).each do |string_handler|
9
+ Mantle::Workers::MessageHandlerWorker.perform_async(
10
+ string_handler, channel, message
11
+ )
12
+ end
13
+ end
14
+
15
+ def channels
16
+ keys
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module Mantle
2
- VERSION = '2.0.0'
2
+ VERSION = '2.0.1'
3
3
  end
@@ -0,0 +1,15 @@
1
+ module Mantle
2
+ module Workers
3
+ class MessageHandlerWorker
4
+ include Sidekiq::Worker
5
+
6
+ sidekiq_options queue: :mantle
7
+
8
+ def perform(string_handler, channel, message)
9
+ handler = Object.const_get(string_handler)
10
+ handler.receive channel, message
11
+ end
12
+ end
13
+ end
14
+ end
15
+
@@ -1,35 +1,22 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Mantle::Configuration do
4
- it 'can set/get message_bus_channels' do
5
- config = Mantle::Configuration.new
6
- config.message_bus_channels = ["update"]
7
- expect(config.message_bus_channels).to eq(Array("update"))
8
- end
9
-
10
- it 'sets default message_bus_channels' do
11
- config = Mantle::Configuration.new
12
- expect(config.message_bus_channels).to eq([])
13
- end
14
-
15
4
  it 'can set/get message_bus_redis' do
16
5
  redis = double("redis")
17
6
  config = Mantle::Configuration.new
18
- config.message_bus_channels = redis
19
- expect(config.message_bus_channels).to eq(redis)
7
+ config.message_bus_redis = redis
8
+ expect(config.message_bus_redis).to eq(redis)
20
9
  end
21
10
 
22
- it 'can set/get message_handler' do
23
- FakeHandler = Class.new
24
-
11
+ it 'can set/get message_handlers' do
25
12
  config = Mantle::Configuration.new
26
- config.message_handler = FakeHandler
27
- expect(config.message_handler).to eq(FakeHandler)
13
+ config.message_handlers = {'a_channel' => 'FakeHandler'}
14
+ expect(config.message_handlers).to eq({'a_channel' => 'FakeHandler'})
28
15
  end
29
16
 
30
17
  it 'configures default message handler' do
31
18
  config = Mantle::Configuration.new
32
- expect(config.message_handler).to eq(Mantle::MessageHandler)
19
+ expect(config.message_handlers).to be_instance_of(Mantle::MessageHandlers)
33
20
  end
34
21
 
35
22
  it 'can set/get logger' do
@@ -55,5 +42,3 @@ describe Mantle::Configuration do
55
42
  expect(config.redis_namespace).to eq(nil)
56
43
  end
57
44
  end
58
-
59
-
@@ -38,6 +38,35 @@ describe Mantle::MessageBus do
38
38
  end
39
39
 
40
40
  describe "#subscribe_to_channels" do
41
+ context 'properly setup message handlers' do
42
+ before :each do
43
+ Mantle.configure do |c|
44
+ c.message_handlers = {
45
+ "order" => "OrderHandler",
46
+ "call" => "CallHandler"
47
+ }
48
+ end
49
+ end
50
+
51
+ it "subscribes to channels configured" do
52
+ redis = double("redis")
53
+ mb = Mantle::MessageBus.new
54
+ mb.redis = redis
55
+
56
+ expect(redis).to receive(:subscribe).with(["order", "call"]) { true }
57
+ mb.subscribe_to_channels
58
+ end
59
+ end
60
+
61
+ it "skips subscription if no channels" do
62
+ redis = double("redis")
63
+ mb = Mantle::MessageBus.new
64
+ mb.redis = redis
65
+
66
+ expect(redis).to_not receive(:subscribe) { true }
67
+ mb.subscribe_to_channels
68
+ end
69
+
41
70
  it "raises without redis connection" do
42
71
  mb = Mantle::MessageBus.new
43
72
  mb.redis = nil
@@ -9,4 +9,3 @@ describe Mantle::MessageHandler do
9
9
  end
10
10
  end
11
11
  end
12
-
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mantle::MessageHandlers do
4
+ describe '#receive_message' do
5
+ it 'enqueues a job for each handler' do
6
+ channel = "person:create"
7
+ message = { "id" => 4 }
8
+ message_handlers = {
9
+ "person:create" => ['FakeHandler', 'OtherFakeHandler']
10
+ }
11
+
12
+ expect {
13
+ Mantle::MessageHandlers.new(message_handlers).receive_message(channel, message)
14
+ }.to change(Mantle::Workers::MessageHandlerWorker.jobs, :size).by(2)
15
+
16
+ args = Mantle::Workers::MessageHandlerWorker.jobs[0]["args"]
17
+ expect(args[0]).to eq("FakeHandler")
18
+ expect(args[1]).to eq(channel)
19
+ expect(args[2]).to eq(message)
20
+
21
+ args = Mantle::Workers::MessageHandlerWorker.jobs[1]["args"]
22
+ expect(args[0]).to eq("OtherFakeHandler")
23
+ expect(args[1]).to eq(channel)
24
+ expect(args[2]).to eq(message)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Mantle::Workers::MessageHandlerWorker do
4
+ let(:channel) { "person:create" }
5
+ let(:message) { {'data' => {'whatever' => 1234}} }
6
+
7
+ describe "#perform" do
8
+ it "delegates to handler with channel/message" do
9
+ class_double('FakeHandler').as_stubbed_const
10
+ FakeHandler.define_singleton_method :receive do |channel, message|
11
+ end
12
+
13
+ expect(FakeHandler).to receive(:receive).with(channel, message)
14
+ Mantle::Workers::MessageHandlerWorker.new.perform("FakeHandler", channel, message)
15
+ end
16
+ end
17
+ end
@@ -7,12 +7,24 @@ describe Mantle do
7
7
  Mantle.configuration.message_bus_redis = "redis"
8
8
  expect(Mantle.configuration.message_bus_redis).to eq("redis")
9
9
  end
10
+
11
+ it 'allows message_handlers to be set' do
12
+ handler_config = { "order" => "OrderHandler" }
13
+ Mantle.configure { |c| c.message_handlers = handler_config }
14
+ expect(Mantle.configuration.message_handlers).to eq(handler_config)
15
+ end
10
16
  end
11
17
 
12
18
  describe ".receive_message" do
13
- it 'delegates to message handler' do
14
- expect(Mantle.configuration.message_handler).to receive(:receive).with("deal:update", {})
15
- Mantle.receive_message("deal:update", {})
19
+ it "delegates to the given channel's message handlers" do
20
+ message = double('message')
21
+
22
+ Mantle.configuration.message_handlers = {
23
+ 'deal:update' => ['MessageHandler', 'MessageHandler2']
24
+ }
25
+
26
+ expect(Mantle.configuration.message_handlers).to receive(:receive_message).with 'deal:update', message
27
+ Mantle.receive_message 'deal:update', message
16
28
  end
17
29
  end
18
30
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mantle
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grant Ammons
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-05-14 00:00:00.000000000 Z
12
+ date: 2015-06-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis
@@ -94,13 +94,16 @@ files:
94
94
  - lib/mantle/configuration.rb
95
95
  - lib/mantle/error.rb
96
96
  - lib/mantle/local_redis.rb
97
+ - lib/mantle/logger.rb
97
98
  - lib/mantle/message.rb
98
99
  - lib/mantle/message_bus.rb
99
100
  - lib/mantle/message_handler.rb
101
+ - lib/mantle/message_handlers.rb
100
102
  - lib/mantle/message_router.rb
101
103
  - lib/mantle/railtie.rb
102
104
  - lib/mantle/version.rb
103
105
  - lib/mantle/workers/catch_up_cleanup_worker.rb
106
+ - lib/mantle/workers/message_handler_worker.rb
104
107
  - lib/mantle/workers/process_worker.rb
105
108
  - mantle.gemspec
106
109
  - spec/lib/mantle/catch_up_spec.rb
@@ -108,9 +111,11 @@ files:
108
111
  - spec/lib/mantle/local_redis_spec.rb
109
112
  - spec/lib/mantle/message_bus_spec.rb
110
113
  - spec/lib/mantle/message_handler_spec.rb
114
+ - spec/lib/mantle/message_handlers_spec.rb
111
115
  - spec/lib/mantle/message_router_spec.rb
112
116
  - spec/lib/mantle/message_spec.rb
113
117
  - spec/lib/mantle/workers/catch_up_cleanup_worker_spec.rb
118
+ - spec/lib/mantle/workers/message_handler_worker_spec.rb
114
119
  - spec/lib/mantle/workers/process_worker_spec.rb
115
120
  - spec/lib/mantle_spec.rb
116
121
  - spec/spec_helper.rb
@@ -133,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
138
  version: '0'
134
139
  requirements: []
135
140
  rubyforge_project:
136
- rubygems_version: 2.4.5
141
+ rubygems_version: 2.4.8
137
142
  signing_key:
138
143
  specification_version: 4
139
144
  summary: Ruby application message bus subscriptions with Sidekiq and Redis Pubsub.
@@ -143,9 +148,11 @@ test_files:
143
148
  - spec/lib/mantle/local_redis_spec.rb
144
149
  - spec/lib/mantle/message_bus_spec.rb
145
150
  - spec/lib/mantle/message_handler_spec.rb
151
+ - spec/lib/mantle/message_handlers_spec.rb
146
152
  - spec/lib/mantle/message_router_spec.rb
147
153
  - spec/lib/mantle/message_spec.rb
148
154
  - spec/lib/mantle/workers/catch_up_cleanup_worker_spec.rb
155
+ - spec/lib/mantle/workers/message_handler_worker_spec.rb
149
156
  - spec/lib/mantle/workers/process_worker_spec.rb
150
157
  - spec/lib/mantle_spec.rb
151
158
  - spec/spec_helper.rb