msgr 1.2.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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}"