mantle 2.0.0 → 2.0.1

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 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