bunny 1.0.7 → 2.24.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 (168) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +92 -87
  3. data/lib/amq/protocol/extensions.rb +2 -0
  4. data/lib/bunny/authentication/credentials_encoder.rb +2 -0
  5. data/lib/bunny/authentication/external_mechanism_encoder.rb +2 -0
  6. data/lib/bunny/authentication/plain_mechanism_encoder.rb +2 -0
  7. data/lib/bunny/channel.rb +485 -186
  8. data/lib/bunny/channel_id_allocator.rb +8 -4
  9. data/lib/bunny/concurrent/atomic_fixnum.rb +2 -0
  10. data/lib/bunny/concurrent/condition.rb +2 -0
  11. data/lib/bunny/concurrent/continuation_queue.rb +37 -13
  12. data/lib/bunny/concurrent/synchronized_sorted_set.rb +2 -0
  13. data/lib/bunny/consumer.rb +20 -13
  14. data/lib/bunny/consumer_tag_generator.rb +6 -2
  15. data/lib/bunny/consumer_work_pool.rb +37 -7
  16. data/lib/bunny/cruby/socket.rb +51 -22
  17. data/lib/bunny/cruby/ssl_socket.rb +68 -5
  18. data/lib/bunny/delivery_info.rb +3 -1
  19. data/lib/bunny/exceptions.rb +27 -4
  20. data/lib/bunny/exchange.rb +35 -29
  21. data/lib/bunny/framing.rb +2 -0
  22. data/lib/bunny/get_response.rb +85 -0
  23. data/lib/bunny/heartbeat_sender.rb +9 -6
  24. data/lib/bunny/message_properties.rb +2 -0
  25. data/lib/bunny/queue.rb +89 -41
  26. data/lib/bunny/reader_loop.rb +72 -28
  27. data/lib/bunny/return_info.rb +2 -0
  28. data/lib/bunny/session.rb +621 -225
  29. data/lib/bunny/socket.rb +7 -12
  30. data/lib/bunny/ssl_socket.rb +7 -12
  31. data/lib/bunny/test_kit.rb +15 -0
  32. data/lib/bunny/timeout.rb +3 -12
  33. data/lib/bunny/timestamp.rb +24 -0
  34. data/lib/bunny/transport.rb +223 -98
  35. data/lib/bunny/version.rb +2 -1
  36. data/lib/bunny/versioned_delivery_tag.rb +2 -0
  37. data/lib/bunny.rb +54 -8
  38. metadata +38 -224
  39. data/.gitignore +0 -22
  40. data/.rspec +0 -3
  41. data/.ruby-version +0 -1
  42. data/.travis.yml +0 -23
  43. data/.yardopts +0 -8
  44. data/ChangeLog.md +0 -1092
  45. data/Gemfile +0 -54
  46. data/LICENSE +0 -21
  47. data/benchmarks/basic_publish/with_128K_messages.rb +0 -35
  48. data/benchmarks/basic_publish/with_1k_messages.rb +0 -35
  49. data/benchmarks/basic_publish/with_4K_messages.rb +0 -35
  50. data/benchmarks/basic_publish/with_64K_messages.rb +0 -35
  51. data/benchmarks/channel_open.rb +0 -28
  52. data/benchmarks/mutex_and_monitor.rb +0 -42
  53. data/benchmarks/queue_declare.rb +0 -29
  54. data/benchmarks/queue_declare_and_bind.rb +0 -29
  55. data/benchmarks/queue_declare_bind_and_delete.rb +0 -29
  56. data/benchmarks/synchronized_sorted_set.rb +0 -53
  57. data/benchmarks/write_vs_write_nonblock.rb +0 -49
  58. data/bin/ci/before_build.sh +0 -31
  59. data/bunny.gemspec +0 -40
  60. data/examples/connection/authentication_failure.rb +0 -16
  61. data/examples/connection/automatic_recovery_with_basic_get.rb +0 -40
  62. data/examples/connection/automatic_recovery_with_client_named_queues.rb +0 -36
  63. data/examples/connection/automatic_recovery_with_multiple_consumers.rb +0 -46
  64. data/examples/connection/automatic_recovery_with_server_named_queues.rb +0 -35
  65. data/examples/connection/channel_level_exception.rb +0 -35
  66. data/examples/connection/disabled_automatic_recovery.rb +0 -34
  67. data/examples/connection/heartbeat.rb +0 -17
  68. data/examples/connection/manually_reconnecting_consumer.rb +0 -23
  69. data/examples/connection/manually_reconnecting_publisher.rb +0 -28
  70. data/examples/connection/unknown_host.rb +0 -16
  71. data/examples/guides/exchanges/direct_exchange_routing.rb +0 -36
  72. data/examples/guides/exchanges/fanout_exchange_routing.rb +0 -28
  73. data/examples/guides/exchanges/headers_exchange_routing.rb +0 -31
  74. data/examples/guides/exchanges/mandatory_messages.rb +0 -30
  75. data/examples/guides/extensions/alternate_exchange.rb +0 -28
  76. data/examples/guides/extensions/basic_nack.rb +0 -33
  77. data/examples/guides/extensions/connection_blocked.rb +0 -35
  78. data/examples/guides/extensions/consumer_cancellation_notification.rb +0 -39
  79. data/examples/guides/extensions/dead_letter_exchange.rb +0 -32
  80. data/examples/guides/extensions/exchange_to_exchange_bindings.rb +0 -29
  81. data/examples/guides/extensions/per_message_ttl.rb +0 -36
  82. data/examples/guides/extensions/per_queue_message_ttl.rb +0 -36
  83. data/examples/guides/extensions/publisher_confirms.rb +0 -28
  84. data/examples/guides/extensions/queue_lease.rb +0 -26
  85. data/examples/guides/extensions/sender_selected_distribution.rb +0 -32
  86. data/examples/guides/getting_started/blabbr.rb +0 -27
  87. data/examples/guides/getting_started/hello_world.rb +0 -20
  88. data/examples/guides/getting_started/weathr.rb +0 -47
  89. data/examples/guides/queues/one_off_consumer.rb +0 -23
  90. data/examples/guides/queues/redeliveries.rb +0 -79
  91. data/lib/bunny/compatibility.rb +0 -24
  92. data/lib/bunny/concurrent/linked_continuation_queue.rb +0 -61
  93. data/lib/bunny/jruby/socket.rb +0 -40
  94. data/lib/bunny/jruby/ssl_socket.rb +0 -53
  95. data/lib/bunny/system_timer.rb +0 -20
  96. data/profiling/basic_publish/with_4K_messages.rb +0 -33
  97. data/repl +0 -3
  98. data/spec/compatibility/queue_declare_spec.rb +0 -44
  99. data/spec/compatibility/queue_declare_with_default_channel_spec.rb +0 -33
  100. data/spec/higher_level_api/integration/basic_ack_spec.rb +0 -71
  101. data/spec/higher_level_api/integration/basic_cancel_spec.rb +0 -76
  102. data/spec/higher_level_api/integration/basic_consume_spec.rb +0 -225
  103. data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +0 -54
  104. data/spec/higher_level_api/integration/basic_get_spec.rb +0 -48
  105. data/spec/higher_level_api/integration/basic_nack_spec.rb +0 -79
  106. data/spec/higher_level_api/integration/basic_publish_spec.rb +0 -89
  107. data/spec/higher_level_api/integration/basic_qos_spec.rb +0 -29
  108. data/spec/higher_level_api/integration/basic_recover_spec.rb +0 -18
  109. data/spec/higher_level_api/integration/basic_reject_spec.rb +0 -74
  110. data/spec/higher_level_api/integration/basic_return_spec.rb +0 -33
  111. data/spec/higher_level_api/integration/channel_close_spec.rb +0 -25
  112. data/spec/higher_level_api/integration/channel_flow_spec.rb +0 -21
  113. data/spec/higher_level_api/integration/channel_open_spec.rb +0 -57
  114. data/spec/higher_level_api/integration/confirm_select_spec.rb +0 -19
  115. data/spec/higher_level_api/integration/connection_spec.rb +0 -400
  116. data/spec/higher_level_api/integration/connection_stop_spec.rb +0 -26
  117. data/spec/higher_level_api/integration/consistent_hash_exchange_spec.rb +0 -50
  118. data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +0 -128
  119. data/spec/higher_level_api/integration/dead_lettering_spec.rb +0 -52
  120. data/spec/higher_level_api/integration/exchange_bind_spec.rb +0 -31
  121. data/spec/higher_level_api/integration/exchange_declare_spec.rb +0 -204
  122. data/spec/higher_level_api/integration/exchange_delete_spec.rb +0 -105
  123. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +0 -40
  124. data/spec/higher_level_api/integration/exclusive_queue_spec.rb +0 -28
  125. data/spec/higher_level_api/integration/heartbeat_spec.rb +0 -31
  126. data/spec/higher_level_api/integration/merry_go_round_spec.rb +0 -85
  127. data/spec/higher_level_api/integration/message_properties_access_spec.rb +0 -95
  128. data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +0 -24
  129. data/spec/higher_level_api/integration/publisher_confirms_spec.rb +0 -77
  130. data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +0 -65
  131. data/spec/higher_level_api/integration/queue_bind_spec.rb +0 -109
  132. data/spec/higher_level_api/integration/queue_declare_spec.rb +0 -190
  133. data/spec/higher_level_api/integration/queue_delete_spec.rb +0 -41
  134. data/spec/higher_level_api/integration/queue_purge_spec.rb +0 -30
  135. data/spec/higher_level_api/integration/queue_unbind_spec.rb +0 -54
  136. data/spec/higher_level_api/integration/read_only_consumer_spec.rb +0 -60
  137. data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +0 -36
  138. data/spec/higher_level_api/integration/tls_connection_spec.rb +0 -127
  139. data/spec/higher_level_api/integration/tx_commit_spec.rb +0 -21
  140. data/spec/higher_level_api/integration/tx_rollback_spec.rb +0 -21
  141. data/spec/higher_level_api/integration/with_channel_spec.rb +0 -25
  142. data/spec/issues/issue100_spec.rb +0 -42
  143. data/spec/issues/issue141_spec.rb +0 -44
  144. data/spec/issues/issue78_spec.rb +0 -75
  145. data/spec/issues/issue83_spec.rb +0 -31
  146. data/spec/issues/issue97_attachment.json +0 -1
  147. data/spec/issues/issue97_spec.rb +0 -176
  148. data/spec/lower_level_api/integration/basic_cancel_spec.rb +0 -69
  149. data/spec/lower_level_api/integration/basic_consume_spec.rb +0 -100
  150. data/spec/spec_helper.rb +0 -64
  151. data/spec/stress/channel_open_stress_spec.rb +0 -51
  152. data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +0 -28
  153. data/spec/stress/concurrent_consumers_stress_spec.rb +0 -69
  154. data/spec/stress/concurrent_publishers_stress_spec.rb +0 -57
  155. data/spec/stress/connection_open_close_spec.rb +0 -40
  156. data/spec/stress/long_running_consumer_spec.rb +0 -83
  157. data/spec/tls/cacert.pem +0 -18
  158. data/spec/tls/client_cert.pem +0 -18
  159. data/spec/tls/client_key.pem +0 -27
  160. data/spec/tls/server_cert.pem +0 -18
  161. data/spec/tls/server_key.pem +0 -27
  162. data/spec/unit/bunny_spec.rb +0 -15
  163. data/spec/unit/concurrent/atomic_fixnum_spec.rb +0 -35
  164. data/spec/unit/concurrent/condition_spec.rb +0 -82
  165. data/spec/unit/concurrent/linked_continuation_queue_spec.rb +0 -35
  166. data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +0 -73
  167. data/spec/unit/system_timer_spec.rb +0 -10
  168. data/spec/unit/version_delivery_tag_spec.rb +0 -28
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "thread"
2
4
 
3
5
  module Bunny
@@ -9,11 +11,17 @@ module Bunny
9
11
  # @private
10
12
  class ReaderLoop
11
13
 
12
- def initialize(transport, session, session_thread)
13
- @transport = transport
14
- @session = session
15
- @session_thread = session_thread
16
- @logger = @session.logger
14
+ def initialize(transport, session, session_error_handler)
15
+ @transport = transport
16
+ @session = session
17
+ @session_error_handler = session_error_handler
18
+ @logger = @session.logger
19
+
20
+ @mutex = Mutex.new
21
+
22
+ @stopping = false
23
+ @stopped = false
24
+ @network_is_down = false
17
25
  end
18
26
 
19
27
 
@@ -29,34 +37,39 @@ module Bunny
29
37
  def run_loop
30
38
  loop do
31
39
  begin
32
- break if @stopping || @network_is_down
40
+ break if @mutex.synchronize { @stopping || @stopped || @network_is_down }
33
41
  run_once
34
- rescue Errno::EBADF => ebadf
35
- break if @stopping
36
- # ignored, happens when we loop after the transport has already been closed
37
- rescue AMQ::Protocol::EmptyResponseError, IOError, SystemCallError => e
38
- break if @stopping
39
- log_exception(e)
42
+ rescue AMQ::Protocol::EmptyResponseError, IOError, SystemCallError, Timeout::Error,
43
+ OpenSSL::OpenSSLError => e
44
+ break if terminate? || @session.closing? || @session.closed?
40
45
 
41
46
  @network_is_down = true
42
-
43
47
  if @session.automatically_recover?
48
+ log_exception(e, level: :warn)
44
49
  @session.handle_network_failure(e)
45
50
  else
46
- @session_thread.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
51
+ log_exception(e)
52
+ @session_error_handler.raise(Bunny::NetworkFailure.new("detected a network failure: #{e.message}", e))
47
53
  end
48
54
  rescue ShutdownSignal => _
55
+ @mutex.synchronize { @stopping = true }
49
56
  break
50
57
  rescue Exception => e
51
- break if @stopping
52
- log_exception(e)
58
+ break if terminate?
59
+ if !(@session.closing? || @session.closed?)
60
+ log_exception(e)
53
61
 
54
- @network_is_down = true
55
- @session_thread.raise(Bunny::NetworkFailure.new("caught an unexpected exception in the network loop: #{e.message}", e))
62
+ @network_is_down = true
63
+ @session_error_handler.raise(Bunny::NetworkFailure.new("caught an unexpected exception in the network loop: #{e.message}", e))
64
+ end
65
+ rescue Errno::EBADF => _ebadf
66
+ break if terminate?
67
+ # ignored, happens when we loop after the transport has already been closed
68
+ @mutex.synchronize { @stopping = true }
56
69
  end
57
70
  end
58
71
 
59
- @stopped = true
72
+ @mutex.synchronize { @stopped = true }
60
73
  end
61
74
 
62
75
  def run_once
@@ -65,7 +78,7 @@ module Bunny
65
78
 
66
79
  if !frame.final? || frame.method_class.has_content?
67
80
  header = @transport.read_next_frame
68
- content = ''
81
+ content = +''
69
82
 
70
83
  if header.body_size > 0
71
84
  loop do
@@ -83,11 +96,21 @@ module Bunny
83
96
  end
84
97
 
85
98
  def stop
86
- @stopping = true
99
+ @mutex.synchronize { @stopping = true }
87
100
  end
88
101
 
89
102
  def stopped?
90
- @stopped
103
+ @mutex.synchronize { @stopped }
104
+ end
105
+
106
+ def stopping?
107
+ @mutex.synchronize { @stopping }
108
+ end
109
+
110
+ def terminate_with(e)
111
+ @mutex.synchronize { @stopping = true }
112
+
113
+ self.raise(e)
91
114
  end
92
115
 
93
116
  def raise(e)
@@ -95,7 +118,14 @@ module Bunny
95
118
  end
96
119
 
97
120
  def join
98
- @thread.join if @thread
121
+ # Thread#join can/would trigger a re-raise of an unhandled exception in this thread.
122
+ # In addition, Thread.handle_interrupt can be used by other libraries or application code
123
+ # that would make this join operation fail with an obscure exception.
124
+ # So we try to save everyone some really unpleasant debugging time by introducing
125
+ # this condition which typically would not evaluate to true anyway.
126
+ #
127
+ # See ruby-amqp/bunny#589 and ruby-amqp/bunny#590 for background.
128
+ @thread.join if @thread && @thread != Thread.current
99
129
  end
100
130
 
101
131
  def kill
@@ -105,12 +135,26 @@ module Bunny
105
135
  end
106
136
  end
107
137
 
108
- def log_exception(e)
109
- @logger.error "Exception in the reader loop: #{e.class.name}: #{e.message}"
110
- @logger.error "Backtrace: "
111
- e.backtrace.each do |line|
112
- @logger.error "\t#{line}"
138
+ protected
139
+
140
+ def log_exception(e, level: :error)
141
+ if !(io_error?(e) && (@session.closing? || @session.closed?))
142
+ @logger.send level, "Exception in the reader loop: #{e.class.name}: #{e.message}"
143
+ @logger.send level, "Backtrace: "
144
+ e.backtrace.each do |line|
145
+ @logger.send level, "\t#{line}"
146
+ end
147
+ end
148
+ end
149
+
150
+ def io_error?(e)
151
+ [AMQ::Protocol::EmptyResponseError, IOError, SystemCallError].any? do |klazz|
152
+ e.is_a?(klazz)
113
153
  end
114
154
  end
155
+
156
+ def terminate?
157
+ @mutex.synchronize { @stopping || @stopped }
158
+ end
115
159
  end
116
160
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Bunny
2
4
  # Wraps AMQ::Protocol::Basic::Return to
3
5
  # provide access to the delivery properties as immutable hash as