bunny-publisher 0.1.1 → 0.1.6

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
  SHA256:
3
- metadata.gz: 5c083b8200bdbe3d30cb2672065e3529c1e1dc78f82514f8d694f83419df279b
4
- data.tar.gz: 38c13c753e4bceeb6f26d344ab050769a874201fb262b47104005bfed3b22466
3
+ metadata.gz: 114f01661b4bf20f7b8e3e0c2a09dba2b969cac13f5b9e1140edd0a8048b8f86
4
+ data.tar.gz: e3a18568ee95e4eca7d5093b9ed3326cffe71c1890c235903d9f4de6395b6efd
5
5
  SHA512:
6
- metadata.gz: 1db69e62d8f38eb35b3a625233af35304ddbeb5ce9af02c3fb162e559813267f3b465dd48e54547a57d1ec9e988d57483e1c03a878b883dab699b14f0588dd43
7
- data.tar.gz: 462fc949e57fcc820e1486a86e4a216229c2bbe2a15792563e1dc45435f97e179cc1d6663f9fbd92a5c74417179631bf87ebadb2e5b674732e39df7d23342681
6
+ metadata.gz: 528c55964119b778c6d7573a489a76b0c315002ccdfff3770a34d26439f76e050e8a629012fe76739cefaffad667201ba1a24b9fa409401fb50b07eb4e6972cd
7
+ data.tar.gz: 933da9ba2d644c5138b4b091dede2935de7bab125cadd7007d1b4a7c311717ceb94bc417fe5251d77f7f11dbe7c757a2c45201d369044cb8b5fe14db6eea2a7e
@@ -1,5 +1,52 @@
1
- ## Changes Between 0.1.0 and 0.1.1
1
+ # Changelog
2
2
 
3
- Minor improvements of unrouted message processing at program exit.
3
+ All notable changes to this project will be documented in this file.
4
4
 
5
- ## Original Release: 0.1.0
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
+
7
+ ## [Unreleased](https://github.com/veeqo/bunny-publisher/compare/v0.1.6...HEAD)
8
+
9
+
10
+ ## [0.1.6](https://github.com/veeqo/bunny-publisher/compare/v0.1.5...v0.1.6) - 2020-11-24
11
+
12
+ ### Fixed
13
+ - [#8](https://github.com/veeqo/bunny-publisher/pull/8) Fix errors on recovery from connection failures
14
+
15
+
16
+ ## [0.1.5](https://github.com/veeqo/bunny-publisher/compare/v0.1.4...v0.1.5) - 2020-11-04
17
+
18
+ ### Fixed
19
+ - [#7](https://github.com/veeqo/bunny-publisher/pull/7) Enforce single channel for threaded apps
20
+
21
+
22
+ ## [0.1.4](https://github.com/veeqo/bunny-publisher/compare/v0.1.3...v0.1.4) - 2020-11-03
23
+
24
+ ### Changed
25
+ - [#5](https://github.com/veeqo/bunny-publisher/pull/5) Test against ruby 2.7.2
26
+
27
+ ### Fixed
28
+ - [#6](https://github.com/veeqo/bunny-publisher/pull/6) Do not share channels between threads
29
+
30
+
31
+ ## [0.1.3](https://github.com/veeqo/bunny-publisher/compare/v0.1.2...v0.1.3) - 2020-09-18
32
+
33
+ ### Changed
34
+ - [#2](https://github.com/veeqo/bunny-publisher/pull/2) Use appraisal gem to control gem versions of tests matrix
35
+ - [#3](https://github.com/veeqo/bunny-publisher/pull/3) Require ruby 2.5
36
+
37
+ ### Fixed
38
+ - [#4](https://github.com/veeqo/bunny-publisher/pull/4) Fix deprecation warnings of ruby 2.7
39
+
40
+
41
+ ## [0.1.2](https://github.com/veeqo/bunny-publisher/compare/v0.1.1...v0.1.2) - 2020-07-30
42
+
43
+ ### Added
44
+ - [846369a](https://github.com/veeqo/bunny-publisher/commit/846369a76a9ae1c38e0a08844a5c992412eac520) Test mode
45
+
46
+
47
+ ## [0.1.1](https://github.com/veeqo/bunny-publisher/compare/v0.1.0...v0.1.1) - 2020-05-21
48
+
49
+ ### Changed
50
+ - [fec490c](https://github.com/veeqo/bunny-publisher/commit/fec490c91a7db9d053dba9afde0736a4ce2dde71) Imrove unrouted messages processing
51
+
52
+ ## [0.1.0](https://github.com/veeqo/bunny-publisher/releases/tag/v0.1.0) - 2020-05-20
data/README.md CHANGED
@@ -111,6 +111,52 @@ end
111
111
 
112
112
  Not implemented yet
113
113
 
114
+ ## Test mode
115
+
116
+ BunnyPublisher also has a test mode which replaces exchange and prevents real connection to RabbitMQ
117
+
118
+ ```ruby
119
+ BunnyPublisher.configure do |c|
120
+ c.test = true # or Rails.env.test?
121
+
122
+ # ...
123
+ end
124
+ ```
125
+
126
+ Now publisher has `#messages`, `#flush!` methods:
127
+
128
+ ```ruby
129
+ describe SomeServiceThatPublishesToRabbitMQ, '#call' do
130
+ subject { described_class.new(some: 'attributes').call }
131
+
132
+ before { BunnyPublisher.flush! }
133
+
134
+ it 'publishes a message' do
135
+ expect { subject }.to change(BunnyPublisher.messages).by(1)
136
+ end
137
+ end
138
+ ```
139
+
140
+ ## Testing
141
+
142
+ Run rabbitmq server (in separate console):
143
+ ```
144
+ docker run --rm -p 5672:5672 -p 15672:15672 rabbitmq:3.8-management-alpine
145
+ ```
146
+
147
+ Run tests with:
148
+
149
+ ```sh
150
+ bundle
151
+ rake
152
+ ```
153
+
154
+ Use [wwtd](https://github.com/grosser/wwtd) to run test matrix:
155
+ ```sh
156
+ gem install wwtd
157
+ wwtd
158
+ ```
159
+
114
160
  ## Contributing
115
161
 
116
162
  Bug reports and pull requests are welcome on GitHub at https://github.com/veeqo/bunny-publisher.
@@ -6,6 +6,7 @@ require 'bunny_publisher/callbacks'
6
6
  require 'bunny_publisher/errors'
7
7
  require 'bunny_publisher/base'
8
8
  require 'bunny_publisher/mandatory'
9
+ require 'bunny_publisher/test'
9
10
 
10
11
  module BunnyPublisher
11
12
  class << self
@@ -20,13 +21,28 @@ module BunnyPublisher
20
21
  def configure
21
22
  require 'ostruct'
22
23
 
23
- config = OpenStruct.new({})
24
+ config = OpenStruct.new(mandatory: false, test: false)
24
25
 
25
26
  yield(config)
26
27
 
27
- klass = Class.new(Base).tap { |k| k.include(::BunnyPublisher::Mandatory) if config.delete_field(:mandatory) }
28
+ klass = Class.new(Base) do
29
+ include ::BunnyPublisher::Mandatory if config.delete_field(:mandatory)
30
+ include ::BunnyPublisher::Test if config.delete_field(:test)
31
+ end
28
32
 
29
- @publisher = klass.new(config.to_h)
33
+ @publisher = klass.new(**config.to_h)
34
+ end
35
+
36
+ def method_missing(method_name, *args)
37
+ if publisher.respond_to?(method_name)
38
+ publisher.send(method_name, *args)
39
+ else
40
+ super
41
+ end
42
+ end
43
+
44
+ def respond_to_missing?(method_name, *args)
45
+ publisher.respond_to?(method_name) || super
30
46
  end
31
47
  end
32
48
  end
@@ -25,13 +25,15 @@ module BunnyPublisher
25
25
  end
26
26
 
27
27
  def publish(message, options = {})
28
- ensure_connection!
28
+ @mutex.synchronize do
29
+ ensure_connection!
29
30
 
30
- run_callback(:before_publish, message, options)
31
- result = run_callback(:around_publish, message, options) { exchange.publish(message, options) }
32
- run_callback(:after_publish, message, options)
31
+ run_callback(:before_publish, message, options)
32
+ result = run_callback(:around_publish, message, options) { exchange.publish(message, options) }
33
+ run_callback(:after_publish, message, options)
33
34
 
34
- result
35
+ result
36
+ end
35
37
  end
36
38
 
37
39
  def close
@@ -43,14 +45,26 @@ module BunnyPublisher
43
45
  private
44
46
 
45
47
  def ensure_connection!
46
- @mutex.synchronize { connect! unless connected? }
48
+ @connection ||= build_connection
49
+
50
+ connection.start if connection.status == :not_connected # Lazy connection initialization.
51
+
52
+ wait_until_connection_ready(connection)
53
+
54
+ @channel ||= connection.create_channel
55
+ @exchange ||= build_exchange
47
56
  end
48
57
 
49
- def connect!
50
- @connection ||= build_connection
51
- connection.start
52
- @channel = connection.create_channel
53
- @exchange = build_exchange
58
+ def wait_until_connection_ready(conn)
59
+ Timeout.timeout((conn.heartbeat || 60) * 2) do # 60 seconds is a default Bunny heartbeat
60
+ loop do
61
+ return if conn.status == :open && conn.transport.open?
62
+
63
+ sleep 0.001
64
+ end
65
+ end
66
+ rescue Timeout::Error
67
+ # Connection recovery takes too long, let the next interaction fail with error then.
54
68
  end
55
69
 
56
70
  def build_connection
@@ -62,9 +76,5 @@ module BunnyPublisher
62
76
 
63
77
  channel.exchange(@exchange_name, @exchange_options)
64
78
  end
65
-
66
- def connected?
67
- @connection&.connected? && channel
68
- end
69
79
  end
70
80
  end
@@ -16,7 +16,7 @@ module BunnyPublisher
16
16
  attr_reader :queue_name, :queue_options
17
17
 
18
18
  def initialize(republish_connection: nil, queue: nil, queue_options: {}, timeout_at_exit: 5, **options)
19
- super(options)
19
+ super(**options)
20
20
 
21
21
  @queue_name = queue
22
22
  @queue_options = queue_options
@@ -51,9 +51,11 @@ module BunnyPublisher
51
51
 
52
52
  attr_reader :republish_connection, :republish_channel, :republish_exchange
53
53
 
54
- def connect!
54
+ def ensure_connection!
55
55
  super
56
56
 
57
+ return if @on_return_set
58
+
57
59
  # `on_return` is called within a frameset of amqp connection.
58
60
  # Any interaction within the same connection leads to error. This is why we need extra connection.
59
61
  # https://github.com/ruby-amqp/bunny/blob/7fb05abf36637557f75a69790be78f9cc1cea807/lib/bunny/session.rb#L683
@@ -62,21 +64,18 @@ module BunnyPublisher
62
64
  else
63
65
  exchange.on_return { |*attrs| on_message_return(*attrs) }
64
66
  end
67
+
68
+ @on_return_set = true
65
69
  end
66
70
 
67
71
  def ensure_republish_connection!
68
- @republish_mutex.synchronize { connect_for_republish! unless connected_for_republish? }
69
- end
72
+ @republish_connection ||= build_republish_connection
73
+ republish_connection.start if republish_connection.status == :not_connected # Lazy connection initialization.
70
74
 
71
- def connected_for_republish?
72
- republish_connection&.connected? && republish_channel
73
- end
75
+ wait_until_connection_ready(republish_connection)
74
76
 
75
- def connect_for_republish!
76
- @republish_connection ||= build_republish_connection
77
- republish_connection.start
78
- @republish_channel = republish_connection.create_channel
79
- @republish_exchange = clone_exchange_for_republish
77
+ @republish_channel ||= republish_connection.create_channel
78
+ @republish_exchange ||= clone_exchange_for_republish
80
79
  end
81
80
 
82
81
  def build_republish_connection
@@ -109,14 +108,16 @@ module BunnyPublisher
109
108
  end
110
109
 
111
110
  def setup_queue_for_republish(return_info, properties, message)
112
- ensure_republish_connection!
111
+ @republish_mutex.synchronize do
112
+ ensure_republish_connection!
113
113
 
114
- queue = declare_republish_queue(return_info, properties, message)
114
+ queue = declare_republish_queue(return_info, properties, message)
115
115
 
116
- # default exchange already has bindings with queues
117
- declare_republish_queue_binding(queue, return_info, properties, message) unless republish_exchange.name == ''
116
+ # default exchange already has bindings with queues
117
+ declare_republish_queue_binding(queue, return_info, properties, message) unless republish_exchange.name == ''
118
118
 
119
- republish_channel.deregister_queue(queue) # we are not going to work with this queue in this channel
119
+ republish_channel.deregister_queue(queue) # we are not going to work with this queue in this channel
120
+ end
120
121
  end
121
122
 
122
123
  def ensure_message_is_unrouted!(return_info, properties, message)
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BunnyPublisher
4
+ # Test module prevents real connections to be made and replaces exchange with array-based TestExchange
5
+ module Test
6
+ class TestExchange < Array
7
+ def publish(message, options = {})
8
+ self << [message, options]
9
+ true
10
+ end
11
+
12
+ # in case if used with Mandatory module included
13
+ def on_return(&block); end
14
+ end
15
+
16
+ def exchange
17
+ @exchange ||= TestExchange.new
18
+ end
19
+
20
+ alias messages exchange
21
+
22
+ def flush!
23
+ exchange.clear
24
+ end
25
+
26
+ alias close flush!
27
+ alias stop flush!
28
+
29
+ private
30
+
31
+ def ensure_connection!; end
32
+ end
33
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BunnyPublisher
4
- VERSION = '0.1.1'
4
+ VERSION = '0.1.6'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bunny-publisher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rustam Sharshenov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-21 00:00:00.000000000 Z
11
+ date: 2020-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -24,20 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: appraisal
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.3.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.3.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
30
44
  requirements:
31
45
  - - ">="
32
46
  - !ruby/object:Gem::Version
33
- version: '0'
47
+ version: '2.0'
34
48
  type: :development
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - ">="
39
53
  - !ruby/object:Gem::Version
40
- version: '0'
54
+ version: '2.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: pry-byebug
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,34 +80,20 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: '1.13'
69
- - !ruby/object:Gem::Dependency
70
- name: rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ">="
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '3.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ">="
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '3.0'
97
97
  description: AMQP publisher for RabbitMQ based on Bunny
98
98
  email:
99
99
  - rustam@sharshenov.com
@@ -101,22 +101,16 @@ executables: []
101
101
  extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
- - ".gitignore"
105
- - ".rspec"
106
- - ".rubocop.yml"
107
- - ".travis.yml"
108
104
  - CHANGELOG.md
109
- - Gemfile
110
105
  - LICENSE.txt
111
106
  - README.md
112
- - Rakefile
113
- - bunny-publisher.gemspec
114
107
  - lib/bunny/publisher.rb
115
108
  - lib/bunny_publisher.rb
116
109
  - lib/bunny_publisher/base.rb
117
110
  - lib/bunny_publisher/callbacks.rb
118
111
  - lib/bunny_publisher/errors.rb
119
112
  - lib/bunny_publisher/mandatory.rb
113
+ - lib/bunny_publisher/test.rb
120
114
  - lib/bunny_publisher/version.rb
121
115
  homepage: https://github.com/veeqo/bunny-publisher
122
116
  licenses:
@@ -133,14 +127,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
127
  requirements:
134
128
  - - ">="
135
129
  - !ruby/object:Gem::Version
136
- version: '0'
130
+ version: '2.5'
137
131
  required_rubygems_version: !ruby/object:Gem::Requirement
138
132
  requirements:
139
133
  - - ">="
140
134
  - !ruby/object:Gem::Version
141
135
  version: '0'
142
136
  requirements: []
143
- rubygems_version: 3.0.8
137
+ rubygems_version: 3.1.4
144
138
  signing_key:
145
139
  specification_version: 4
146
140
  summary: AMQP publisher for RabbitMQ based on Bunny
data/.gitignore DELETED
@@ -1,14 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- /Gemfile.lock
10
- /.ruby-gemset
11
- /.ruby-version
12
-
13
- # rspec failure tracking
14
- .rspec_status
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --format documentation
2
- --color
3
- --require spec_helper
@@ -1,16 +0,0 @@
1
- Layout/LineLength:
2
- Max: 120
3
- Exclude:
4
- - "spec/**/*"
5
-
6
- Lint/AmbiguousBlockAssociation:
7
- Exclude:
8
- - "spec/**/*"
9
-
10
- Metrics/BlockLength:
11
- Exclude:
12
- - "spec/**/*"
13
-
14
- Style/EvalWithLocation:
15
- Exclude:
16
- - "spec/**/*"
@@ -1,16 +0,0 @@
1
- ---
2
- dist: xenial
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - 2.5.8
7
- - 2.6.6
8
- - 2.7.1
9
- env:
10
- - BUNNY_VERSION="~> 2.15"
11
- - BUNNY_VERSION="2.10.0"
12
-
13
- before_install: gem install bundler
14
- before_script:
15
- - ".ci/install_rabbitmq"
16
- bundler_args: --jobs 3 --retry 3
data/Gemfile DELETED
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
-
7
- # Specify your gem's dependencies in bunny-publisher.gemspec
8
- gemspec
9
-
10
- gem 'bunny', ENV.fetch('BUNNY_VERSION', '~> 2.15')
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
5
-
6
- RSpec::Core::RakeTask.new(:spec)
7
-
8
- task default: :spec
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'bunny_publisher/version'
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = 'bunny-publisher'
9
- spec.version = BunnyPublisher::VERSION
10
- spec.authors = ['Rustam Sharshenov']
11
- spec.email = ['rustam@sharshenov.com']
12
-
13
- spec.summary = 'AMQP publisher for RabbitMQ based on Bunny'
14
- spec.description = 'AMQP publisher for RabbitMQ based on Bunny'
15
- spec.homepage = 'https://github.com/veeqo/bunny-publisher'
16
- spec.license = 'MIT'
17
-
18
- if spec.respond_to?(:metadata)
19
- spec.metadata['homepage_uri'] = spec.homepage
20
- spec.metadata['source_code_uri'] = spec.homepage
21
- spec.metadata['changelog_uri'] = 'https://github.com/veeqo/bunny-publisher/blob/master/CHANGELOG.md'
22
- end
23
-
24
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
25
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|\.ci)/}) }
26
- end
27
- spec.require_paths = ['lib']
28
-
29
- spec.add_dependency 'bunny', '~> 2.10'
30
-
31
- spec.add_development_dependency 'bundler'
32
- spec.add_development_dependency 'pry-byebug'
33
- spec.add_development_dependency 'rabbitmq_http_api_client', '~> 1.13'
34
- spec.add_development_dependency 'rake'
35
- spec.add_development_dependency 'rspec'
36
- end