msgr 1.2.0 → 1.4.0

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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +8 -0
  3. data/.github/workflows/test.yml +79 -0
  4. data/.rubocop.yml +12 -47
  5. data/Appraisals +23 -0
  6. data/CHANGELOG.md +87 -5
  7. data/Gemfile +9 -15
  8. data/README.md +11 -28
  9. data/Rakefile +10 -6
  10. data/bin/msgr +1 -0
  11. data/gemfiles/rails_5.2.gemfile +15 -0
  12. data/gemfiles/rails_6.0.gemfile +15 -0
  13. data/gemfiles/rails_6.1.gemfile +15 -0
  14. data/gemfiles/rails_7.0.gemfile +15 -0
  15. data/gemfiles/rails_head.gemfile +15 -0
  16. data/lib/msgr/binding.rb +13 -8
  17. data/lib/msgr/channel.rb +7 -10
  18. data/lib/msgr/cli.rb +26 -20
  19. data/lib/msgr/client.rb +27 -25
  20. data/lib/msgr/connection.rb +14 -2
  21. data/lib/msgr/consumer.rb +2 -3
  22. data/lib/msgr/dispatcher.rb +7 -9
  23. data/lib/msgr/logging.rb +2 -0
  24. data/lib/msgr/message.rb +1 -2
  25. data/lib/msgr/railtie.rb +14 -75
  26. data/lib/msgr/route.rb +2 -5
  27. data/lib/msgr/routes.rb +2 -0
  28. data/lib/msgr/tasks/msgr/drain.rake +11 -0
  29. data/lib/msgr/test_pool.rb +1 -3
  30. data/lib/msgr/version.rb +1 -1
  31. data/lib/msgr.rb +2 -3
  32. data/msgr.gemspec +8 -6
  33. data/renovate.json +5 -0
  34. data/scripts/simple_test.rb +3 -4
  35. data/spec/fixtures/{msgr-routes-test-1.rb → msgr_routes_test_1.rb} +0 -0
  36. data/spec/fixtures/msgr_routes_test_drain.rb +5 -0
  37. data/spec/integration/dummy/Rakefile +1 -1
  38. data/spec/{msgr/support/.keep → integration/dummy/app/assets/config/manifest.js} +0 -0
  39. data/spec/integration/dummy/bin/bundle +1 -1
  40. data/spec/integration/dummy/bin/rails +1 -1
  41. data/spec/integration/dummy/config/application.rb +1 -1
  42. data/spec/integration/dummy/config/boot.rb +2 -2
  43. data/spec/integration/dummy/config/environment.rb +1 -1
  44. data/spec/integration/dummy/config/rabbitmq.yml +1 -1
  45. data/spec/integration/msgr/dispatcher_spec.rb +28 -12
  46. data/spec/integration/msgr/railtie_spec.rb +10 -120
  47. data/spec/integration/spec_helper.rb +2 -3
  48. data/spec/integration/{msgr_spec.rb → test_controller_spec.rb} +1 -1
  49. data/spec/unit/msgr/client_spec.rb +83 -0
  50. data/spec/{msgr → unit}/msgr/connection_spec.rb +1 -1
  51. data/spec/{msgr → unit}/msgr/consumer_spec.rb +0 -0
  52. data/spec/unit/msgr/dispatcher_spec.rb +45 -0
  53. data/spec/{msgr → unit}/msgr/route_spec.rb +29 -14
  54. data/spec/{msgr → unit}/msgr/routes_spec.rb +32 -35
  55. data/spec/{msgr → unit}/msgr_spec.rb +26 -18
  56. data/spec/{msgr → unit}/spec_helper.rb +1 -1
  57. data/spec/unit/support/.keep +0 -0
  58. metadata +43 -36
  59. data/.travis.yml +0 -43
  60. data/gemfiles/Gemfile.rails-4-2 +0 -7
  61. data/gemfiles/Gemfile.rails-5-0 +0 -7
  62. data/gemfiles/Gemfile.rails-5-1 +0 -7
  63. data/gemfiles/Gemfile.rails-5-2 +0 -7
  64. data/gemfiles/Gemfile.rails-master +0 -14
  65. data/spec/msgr/msgr/client_spec.rb +0 -60
  66. data/spec/msgr/msgr/dispatcher_spec.rb +0 -44
  67. data/spec/support/setup.rb +0 -29
data/lib/msgr/channel.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Msgr
2
4
  class Channel
3
5
  include Logging
@@ -20,17 +22,17 @@ module Msgr
20
22
  @channel.topic(prefix(EXCHANGE_NAME), durable: true).tap do |ex|
21
23
  log(:debug) do
22
24
  "Created exchange #{ex.name} (type: #{ex.type}, " \
23
- "durable: #{ex.durable?}, auto_delete: #{ex.auto_delete?})"
25
+ "durable: #{ex.durable?}, auto_delete: #{ex.auto_delete?})"
24
26
  end
25
27
  end
26
28
  end
27
29
  end
28
30
 
29
- def queue(name)
30
- @channel.queue(prefix(name), durable: true).tap do |queue|
31
+ def queue(name, **opts)
32
+ @channel.queue(prefix(name), durable: true, **opts).tap do |queue|
31
33
  log(:debug) do
32
34
  "Create queue #{queue.name} (durable: #{queue.durable?}, " \
33
- "auto_delete: #{queue.auto_delete?})"
35
+ "auto_delete: #{queue.auto_delete?})"
34
36
  end
35
37
  end
36
38
  end
@@ -53,13 +55,8 @@ module Msgr
53
55
  log(:debug) { "Nacked message: #{delivery_tag}" }
54
56
  end
55
57
 
56
- def reject(delivery_tag, requeue = true)
57
- @channel.reject delivery_tag, requeue
58
- log(:debug) { "Rejected message: #{delivery_tag}" }
59
- end
60
-
61
58
  def close
62
59
  @channel.close if @channel.open?
63
60
  end
64
61
  end
65
- end
62
+ end
data/lib/msgr/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optionparser'
2
4
 
3
5
  module Msgr
@@ -8,7 +10,8 @@ module Msgr
8
10
  @options = options
9
11
 
10
12
  if !File.exist?(options[:require]) ||
11
- (File.directory?(options[:require]) && !File.exist?("#{options[:require]}/config/application.rb"))
13
+ (File.directory?(options[:require]) &&
14
+ !File.exist?("#{options[:require]}/config/application.rb"))
12
15
  raise <<~ERR
13
16
  Rails application or required ruby file not found: #{options[:require]}
14
17
  ERR
@@ -22,15 +25,13 @@ module Msgr
22
25
  require 'rails'
23
26
  if ::Rails::VERSION::MAJOR == 4
24
27
  require File.expand_path("#{options[:require]}/config/application.rb")
25
- ::Rails::Application.initializer "msgr.eager_load" do
28
+ ::Rails::Application.initializer 'msgr.eager_load' do
26
29
  ::Rails.application.config.eager_load = true
27
30
  end
28
- require 'msgr/railtie'
29
- require File.expand_path("#{options[:require]}/config/environment.rb")
30
- else
31
- require 'msgr/railtie'
32
- require File.expand_path("#{options[:require]}/config/environment.rb")
33
31
  end
32
+
33
+ require 'msgr/railtie'
34
+ require File.expand_path("#{options[:require]}/config/environment.rb")
34
35
  else
35
36
  require(options[:require])
36
37
  end
@@ -40,17 +41,16 @@ module Msgr
40
41
  Signal.trap('INT') { w.puts 'INT' }
41
42
  Signal.trap('TERM') { w.puts 'TERM' }
42
43
 
43
- Msgr.logger = Logger.new(STDOUT)
44
+ Msgr.logger = Logger.new($stdout)
44
45
  Msgr.client.start
45
46
 
46
- while readable = IO.select([r])
47
- case readable.first[0].gets.strip
48
- when 'INT', 'TERM'
49
- Msgr.client.stop
50
- break
51
- else
52
- exit 1
53
- end
47
+ # Wait until we receive a signal
48
+ readable = IO.select([r])
49
+ case readable.first[0].gets.strip
50
+ when 'INT', 'TERM' # Safe shutdown
51
+ Msgr.client.stop
52
+ else # Error
53
+ exit 1
54
54
  end
55
55
  end
56
56
 
@@ -61,18 +61,24 @@ module Msgr
61
61
 
62
62
  private
63
63
 
64
- def parse(argv)
64
+ def parse(_argv)
65
65
  options = {
66
66
  require: Dir.pwd,
67
- environment: 'development'
67
+ environment: 'development',
68
68
  }
69
69
 
70
70
  OptionParser.new do |o|
71
- o.on '-r', '--require [PATH|DIR]', 'Location of Rails application (default to current directory)' do |arg|
71
+ o.on(
72
+ '-r', '--require [PATH|DIR]',
73
+ 'Location of Rails application (default to current directory)',
74
+ ) do |arg|
72
75
  options[:require] = arg
73
76
  end
74
77
 
75
- o.on '-e', '--environment [env]', 'Rails environment (default to development)' do |arg|
78
+ o.on(
79
+ '-e', '--environment [env]',
80
+ 'Rails environment (default to development)',
81
+ ) do |arg|
76
82
  options[:environment] = arg
77
83
  end
78
84
  end.parse!
data/lib/msgr/client.rb CHANGED
@@ -2,37 +2,31 @@
2
2
 
3
3
  require 'uri'
4
4
  require 'cgi'
5
+ require 'json'
5
6
 
6
7
  module Msgr
7
- # rubocop:disable Metrics/ClassLength
8
8
  class Client
9
9
  include Logging
10
10
 
11
11
  attr_reader :config
12
12
 
13
- # rubocop:disable MethodLength
14
13
  def initialize(config = {})
15
14
  @config = {
16
15
  host: '127.0.0.1',
17
16
  vhost: '/',
18
- max: 2
17
+ max: 2,
19
18
  }
20
19
 
21
- @config.merge! parse(config.delete(:uri)) if config.key?(:uri)
20
+ @config.merge! parse(config.delete(:uri)) if config[:uri]
22
21
  @config.merge! config.symbolize_keys
23
22
 
24
23
  @mutex = ::Mutex.new
25
- @routes = Routes.new
24
+ @routes = load_routes
26
25
  @pid ||= ::Process.pid
27
26
 
28
27
  log(:debug) { "Created new client on process ##{@pid}..." }
29
28
  end
30
- # rubocop:enable all
31
29
 
32
- # rubocop:disable AbcSize
33
- # rubocop:disable MethodLength
34
- # rubocop:disable PerceivedComplexity
35
- # rubocop:disable CyclomaticComplexity
36
30
  def uri
37
31
  @uri = begin
38
32
  uri = ::URI.parse('amqp://localhost')
@@ -50,7 +44,6 @@ module Msgr
50
44
  uri
51
45
  end
52
46
  end
53
- # rubocop:enable all
54
47
 
55
48
  def running?
56
49
  mutex.synchronize do
@@ -59,7 +52,6 @@ module Msgr
59
52
  end
60
53
  end
61
54
 
62
- # rubocop:disable AbcSize
63
55
  def start
64
56
  mutex.synchronize do
65
57
  check_process!
@@ -67,12 +59,9 @@ module Msgr
67
59
 
68
60
  log(:debug) { "Start on #{uri}..." }
69
61
 
70
- @routes << config[:routing_file] if config[:routing_file].present?
71
- @routes.reload
72
62
  connection.bind(@routes)
73
63
  end
74
64
  end
75
- # rubocop:enable all
76
65
 
77
66
  def connect
78
67
  mutex.synchronize do
@@ -85,7 +74,6 @@ module Msgr
85
74
  end
86
75
  end
87
76
 
88
- # rubocop:disable AbcSize
89
77
  def stop(opts = {})
90
78
  mutex.synchronize do
91
79
  check_process!
@@ -100,7 +88,6 @@ module Msgr
100
88
  reset
101
89
  end
102
90
  end
103
- # rubocop:enable all
104
91
 
105
92
  def purge(release: false)
106
93
  mutex.synchronize do
@@ -112,6 +99,15 @@ module Msgr
112
99
  end
113
100
  end
114
101
 
102
+ ##
103
+ # Purge all queues known to Msgr, if they exist.
104
+ #
105
+ def drain
106
+ @routes.each do |route|
107
+ connection.purge_queue(route.name)
108
+ end
109
+ end
110
+
115
111
  def publish(payload, opts = {})
116
112
  mutex.synchronize do
117
113
  check_process!
@@ -149,9 +145,10 @@ module Msgr
149
145
 
150
146
  def check_process!
151
147
  return if ::Process.pid == @pid
148
+
152
149
  log(:warn) do
153
150
  "Fork detected. Reset internal state. (Old PID: #{@pid} / " \
154
- "New PID: #{::Process.pid}"
151
+ "New PID: #{::Process.pid}"
155
152
  end
156
153
 
157
154
  reset
@@ -178,22 +175,27 @@ module Msgr
178
175
  @dispatcher = nil
179
176
  end
180
177
 
181
- # rubocop:disable AbcSize
182
178
  def parse(uri)
183
179
  # Legacy parsing of URI configuration; does not follow usual
184
180
  # AMQP vhost encoding but used regular URL path
185
181
  uri = ::URI.parse(uri)
186
182
 
187
183
  config = {}
188
- config[:user] ||= uri.user if uri.user
189
- config[:pass] ||= uri.password if uri.password
190
- config[:host] ||= uri.host if uri.host
191
- config[:port] ||= uri.port if uri.port
192
- config[:vhost] ||= uri.path unless uri.path.empty?
184
+ config[:user] ||= uri.user if uri.user
185
+ config[:pass] ||= uri.password if uri.password
186
+ config[:host] ||= uri.host if uri.host
187
+ config[:port] ||= uri.port if uri.port
188
+ config[:vhost] ||= uri.path unless uri.path.empty?
193
189
  config[:ssl] ||= uri.scheme.casecmp('amqps').zero?
194
190
 
195
191
  config
196
192
  end
197
- # rubocop:enable all
193
+
194
+ def load_routes
195
+ Routes.new.tap do |routes|
196
+ routes << config[:routing_file] if config[:routing_file].present?
197
+ routes.reload
198
+ end
199
+ end
198
200
  end
199
201
  end
@@ -3,7 +3,6 @@
3
3
  require 'bunny'
4
4
 
5
5
  module Msgr
6
- # rubocop:disable Metrics/ClassLength
7
6
  class Connection
8
7
  include Logging
9
8
 
@@ -49,6 +48,7 @@ module Msgr
49
48
 
50
49
  def release
51
50
  return if bindings.empty?
51
+
52
52
  log(:debug) { "Release bindings (#{bindings.size})..." }
53
53
 
54
54
  bindings.each(&:release)
@@ -56,6 +56,7 @@ module Msgr
56
56
 
57
57
  def delete
58
58
  return if bindings.empty?
59
+
59
60
  log(:debug) { "Delete bindings (#{bindings.size})..." }
60
61
 
61
62
  bindings.each(&:delete)
@@ -63,11 +64,22 @@ module Msgr
63
64
 
64
65
  def purge(**kwargs)
65
66
  return if bindings.empty?
67
+
66
68
  log(:debug) { "Purge bindings (#{bindings.size})..." }
67
69
 
68
70
  bindings.each {|b| b.purge(**kwargs) }
69
71
  end
70
72
 
73
+ def purge_queue(name)
74
+ # Creating the queue in passive mode ensures that queues that do not exist
75
+ # won't be created just to purge them.
76
+ # That requires creating a new channel every time, as exceptions (on
77
+ # missing queues) invalidate the channel.
78
+ channel.queue(name, passive: true).purge
79
+ rescue Bunny::NotFound
80
+ nil
81
+ end
82
+
71
83
  def bindings
72
84
  @bindings ||= []
73
85
  end
@@ -76,7 +88,7 @@ module Msgr
76
88
  if routes.empty?
77
89
  log(:warn) do
78
90
  "No routes to bound to. Bind will have no effect:\n" \
79
- " #{routes.inspect}"
91
+ " #{routes.inspect}"
80
92
  end
81
93
  else
82
94
  bind_all(routes)
data/lib/msgr/consumer.rb CHANGED
@@ -5,6 +5,7 @@ module Msgr
5
5
  include Logging
6
6
 
7
7
  attr_reader :message
8
+
8
9
  delegate :payload, to: :@message
9
10
  delegate :action, to: :'@message.route'
10
11
  delegate :consumer, to: :'@message.consumer'
@@ -14,9 +15,7 @@ module Msgr
14
15
  @auto_ack || @auto_ack.nil?
15
16
  end
16
17
 
17
- def auto_ack=(val)
18
- @auto_ack = val
19
- end
18
+ attr_writer :auto_ack
20
19
  end
21
20
 
22
21
  def dispatch(message)
@@ -27,9 +27,6 @@ module Msgr
27
27
  end
28
28
  end
29
29
 
30
- # rubocop:disable Metrics/AbcSize
31
- # rubocop:disable Metrics/MethodLength
32
- # rubocop:disable Metrics/CyclomaticComplexity
33
30
  def dispatch(message)
34
31
  consumer_class = Object.const_get message.route.consumer
35
32
 
@@ -37,17 +34,18 @@ module Msgr
37
34
 
38
35
  consumer_class.new.dispatch message
39
36
 
40
- # Acknowledge message unless it is already acknowledged or auto_ack is disabled.
41
- message.ack unless message.acked? or not consumer_class.auto_ack?
42
- rescue => error
37
+ # Acknowledge message only if it is not already acknowledged and auto
38
+ # acknowledgment is enabled.
39
+ message.ack unless message.acked? || !consumer_class.auto_ack?
40
+ rescue StandardError => e
43
41
  message.nack unless message.acked?
44
42
 
45
43
  log(:error) do
46
- "Dispatcher error: #{error.class.name}: #{error}\n" +
47
- error.backtrace.join("\n")
44
+ "Dispatcher error: #{e.class.name}: #{e}\n" +
45
+ e.backtrace.join("\n")
48
46
  end
49
47
 
50
- raise error if config[:raise_exceptions]
48
+ raise e if config[:raise_exceptions]
51
49
  ensure
52
50
  if defined?(ActiveRecord) &&
53
51
  ActiveRecord::Base.connection_pool.active_connection?
data/lib/msgr/logging.rb CHANGED
@@ -3,7 +3,9 @@
3
3
  module Msgr
4
4
  module Logging
5
5
  def log(level)
6
+ # rubocop:disable Style/SafeNavigation - Msgr.logger can be false
6
7
  Msgr.logger.send(level) { "#{log_name} #{yield}" } if Msgr.logger
8
+ # rubocop:enable all
7
9
  end
8
10
 
9
11
  def log_name
data/lib/msgr/message.rb CHANGED
@@ -11,8 +11,7 @@ module Msgr
11
11
  @payload = payload
12
12
  @route = route
13
13
 
14
- # rubocop:disable Style/GuardClause
15
- if content_type == 'application/json'
14
+ if content_type == 'application/json' # rubocop:disable Style/GuardClause
16
15
  @payload = JSON.parse(payload)
17
16
  @payload.symbolize_keys! if @payload.respond_to? :symbolize_keys!
18
17
  end
data/lib/msgr/railtie.rb CHANGED
@@ -4,92 +4,31 @@ module Msgr
4
4
  class Railtie < ::Rails::Railtie
5
5
  config.msgr = ActiveSupport::OrderedOptions.new
6
6
 
7
- if File.exist?("#{Rails.root}/app/consumers")
8
- config.autoload_paths << File.expand_path("#{Rails.root}/app/consumers")
9
- end
10
-
11
7
  initializer 'msgr.logger' do |app|
12
8
  app.config.msgr.logger ||= Rails.logger
13
9
  end
14
10
 
15
- # Start msgr
16
11
  initializer 'msgr.start' do
17
12
  config.after_initialize do |app|
18
13
  Msgr.logger = app.config.msgr.logger
19
-
20
- self.class.load app.config.msgr
14
+ self.class.load(app.config_for(:rabbitmq).symbolize_keys)
21
15
  end
22
16
  end
23
17
 
24
- class << self
25
- def load(rails_config)
26
- cfg = parse_config load_config rails_config
27
- return unless cfg # no config given -> does not load Msgr
28
-
29
- Msgr.config = cfg
30
- Msgr.client.connect if cfg[:checkcredentials]
31
- Msgr.start if cfg[:autostart]
32
- end
33
-
34
- def parse_config(cfg)
35
- unless cfg.is_a? Hash
36
- Rails.logger.warn '[Msgr] Could not load rabbitmq config: Config must be a Hash'
37
- return nil
38
- end
39
-
40
- unless cfg[Rails.env].is_a?(Hash)
41
- Rails.logger.warn "Could not load rabbitmq config for environment \"#{Rails.env}\": is not a Hash"
42
- return nil
43
- end
44
-
45
- cfg = HashWithIndifferentAccess.new cfg[Rails.env]
46
- unless cfg[:uri]
47
- raise ArgumentError.new('Could not load rabbitmq environment config: URI missing.')
48
- end
49
-
50
- case cfg[:autostart]
51
- when true, 'true', 'enabled'
52
- cfg[:autostart] = true
53
- when false, 'false', 'disabled', nil
54
- cfg[:autostart] = false
55
- else
56
- raise ArgumentError.new("Invalid value for rabbitmq config autostart: \"#{cfg[:autostart]}\"")
57
- end
58
-
59
- case cfg[:checkcredentials]
60
- when true, 'true', 'enabled', nil
61
- cfg[:checkcredentials] = true
62
- when false, 'false', 'disabled'
63
- cfg[:checkcredentials] = false
64
- else
65
- raise ArgumentError.new("Invalid value for rabbitmq config checkcredentials: \"#{cfg[:checkcredentials]}\"")
66
- end
67
-
68
- case cfg[:raise_exceptions]
69
- when true, 'true', 'enabled'
70
- cfg[:raise_exceptions] = true
71
- when false, 'false', 'disabled', nil
72
- cfg[:raise_exceptions] = false
73
- else
74
- raise ArgumentError.new("Invalid value for rabbitmq config raise_exceptions: \"#{cfg[:raise_exceptions]}\"")
75
- end
76
-
77
- cfg[:routing_file] ||= Rails.root.join('config/msgr.rb').to_s
78
- cfg
79
- end
80
-
81
- def load_config(options)
82
- if options.rabbitmq_config || !Rails.application.respond_to?(:config_for)
83
- load_file options.rabbitmq_config || Rails.root.join('config', 'rabbitmq.yml')
84
- else
85
- conf = Rails.application.config_for :rabbitmq
86
-
87
- {Rails.env.to_s => conf}
88
- end
89
- end
18
+ rake_tasks do
19
+ load File.expand_path('tasks/msgr/drain.rake', __dir__)
20
+ end
90
21
 
91
- def load_file(path)
92
- YAML.safe_load ERB.new(File.read(path)).result
22
+ class << self
23
+ def load(config)
24
+ # Set defaults
25
+ config.reverse_merge!(
26
+ checkcredentials: true,
27
+ routing_file: Rails.root.join('config/msgr.rb').to_s,
28
+ )
29
+
30
+ Msgr.config = config
31
+ Msgr.client.connect if config.fetch(:checkcredentials)
93
32
  end
94
33
  end
95
34
  end
data/lib/msgr/route.rb CHANGED
@@ -4,10 +4,7 @@ module Msgr
4
4
  class Route
5
5
  attr_reader :consumer, :action, :opts
6
6
 
7
- MATCH_REGEXP = /\A(?<consumer>\w+)#(?<action>\w+)\z/
8
-
9
- # rubocop:disable Metrics/AbcSize
10
- # rubocop:disable Metrics/MethodLength
7
+ MATCH_REGEXP = %r{\A(?<consumer>(?:\w+/)*\w+)#(?<action>\w+)\z}.freeze
11
8
  def initialize(key, opts = {})
12
9
  @opts = opts
13
10
  raise ArgumentError.new 'Missing `to` options.' unless @opts[:to]
@@ -19,7 +16,7 @@ module Msgr
19
16
  unless result
20
17
  raise ArgumentError.new \
21
18
  "Invalid consumer format: #{opts[:to].strip.to_s.inspect}. " \
22
- 'Must be `consumer_class#action`.'
19
+ 'Must be `name/space/consumer_class#action`.'
23
20
  end
24
21
 
25
22
  @consumer = "#{result[:consumer].camelize}Consumer"
data/lib/msgr/routes.rb CHANGED
@@ -3,7 +3,9 @@
3
3
  module Msgr
4
4
  class Routes
5
5
  include Logging
6
+
6
7
  attr_reader :routes
8
+
7
9
  delegate :each, :empty?, :size, :any?, to: :@routes
8
10
 
9
11
  def initialize
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :msgr do
4
+ desc 'Drain all known queues'
5
+ task drain: :environment do
6
+ client = Msgr.client
7
+
8
+ client.connect
9
+ client.drain
10
+ end
11
+ end
@@ -31,8 +31,6 @@ module Msgr
31
31
 
32
32
  private
33
33
 
34
- # rubocop:disable Metrics/AbcSize
35
- # rubocop:disable Metrics/MethodLength
36
34
  def ns_run(count: 1, timeout: 5)
37
35
  received = 0
38
36
 
@@ -59,7 +57,7 @@ module Msgr
59
57
 
60
58
  class << self
61
59
  def new(*args)
62
- @instance ||= super(*args)
60
+ @instance ||= super(*args) # rubocop:disable Naming/MemoizedInstanceVariableName
63
61
  end
64
62
 
65
63
  def run(*args)
data/lib/msgr/version.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Msgr
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 2
6
+ MINOR = 4
7
7
  PATCH = 0
8
8
  STAGE = nil
9
9
  STRING = [MAJOR, MINOR, PATCH, STAGE].reject(&:nil?).join('.')
data/lib/msgr.rb CHANGED
@@ -25,7 +25,8 @@ require 'msgr/railtie' if defined? Rails
25
25
 
26
26
  module Msgr
27
27
  class << self
28
- attr_writer :client, :config
28
+ attr_writer :client, :config, :logger
29
+
29
30
  delegate :publish, to: :client
30
31
 
31
32
  def config
@@ -45,8 +46,6 @@ module Msgr
45
46
  @logger
46
47
  end
47
48
 
48
- attr_writer :logger
49
-
50
49
  def start
51
50
  client.start
52
51
  client
data/msgr.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- lib = File.expand_path('../lib', __FILE__)
3
+ lib = File.expand_path('lib', __dir__)
4
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  require 'msgr/version'
@@ -9,23 +9,25 @@ Gem::Specification.new do |spec|
9
9
  spec.name = 'msgr'
10
10
  spec.version = Msgr::VERSION
11
11
  spec.authors = ['Jan Graichen']
12
- spec.email = ['jg@altimos.de']
12
+ spec.email = ['jgraichen@altimos.de']
13
13
  spec.description = 'Msgr: Rails-like Messaging Framework'
14
14
  spec.summary = 'Msgr: Rails-like Messaging Framework'
15
15
  spec.homepage = 'https://github.com/jgraichen/msgr'
16
16
  spec.license = 'MIT'
17
17
 
18
+ spec.metadata = {
19
+ 'rubygems_mfa_required' => 'true',
20
+ }
21
+
18
22
  spec.files = `git ls-files -z`.split("\x0")
19
23
  spec.executables = spec.files.grep(%r{^bin/}) {|f| File.basename(f) }
20
24
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
25
  spec.require_paths = %w[lib]
22
26
 
27
+ spec.required_ruby_version = '>= 2.5'
28
+
23
29
  spec.add_dependency 'activesupport'
24
30
  spec.add_dependency 'bunny', '>= 1.4', '< 3.0'
25
31
 
26
32
  spec.add_development_dependency 'bundler'
27
-
28
- if ENV['TRAVIS_BUILD_NUMBER']
29
- spec.version = "#{spec.version}.1.b#{ENV['TRAVIS_BUILD_NUMBER']}"
30
- end
31
33
  end
data/renovate.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": [
3
+ "config:base"
4
+ ]
5
+ }
@@ -19,7 +19,6 @@ class TestConsumer < Msgr::Consumer
19
19
  end
20
20
  end
21
21
 
22
- #
23
22
  class NullPool
24
23
  def initialize(*); end
25
24
 
@@ -29,7 +28,7 @@ class NullPool
29
28
  end
30
29
 
31
30
  @client = Msgr::Client.new user: 'guest', password: 'guest',
32
- max: 4 # , pool_class: 'NullPool'
31
+ max: 4 # , pool_class: 'NullPool'
33
32
 
34
33
  @client.routes.configure do
35
34
  route 'abc.#', to: 'test#index'
@@ -45,9 +44,9 @@ end
45
44
 
46
45
  begin
47
46
  sleep
48
- rescue Interrupt
47
+ rescue Interrupt # rubocop:disable Lint/SuppressedException
49
48
  ensure
50
49
  @client.stop timeout: 10, delete: true
51
50
  end
52
51
 
53
- $stderr.puts "COUNTER: #{@counter}"
52
+ warn "COUNTER: #{@counter}"