amq-client 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/.gitignore +8 -0
  2. data/.gitmodules +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +7 -0
  5. data/.yardopts +1 -0
  6. data/CONTRIBUTORS +3 -0
  7. data/Gemfile +27 -0
  8. data/LICENSE +20 -0
  9. data/README.textile +61 -0
  10. data/amq-client.gemspec +34 -0
  11. data/bin/jenkins.sh +23 -0
  12. data/bin/set_test_suite_realms_up.sh +24 -0
  13. data/examples/coolio_adapter/basic_consume.rb +49 -0
  14. data/examples/coolio_adapter/basic_consume_with_acknowledgements.rb +43 -0
  15. data/examples/coolio_adapter/basic_consume_with_rejections.rb +43 -0
  16. data/examples/coolio_adapter/basic_publish.rb +35 -0
  17. data/examples/coolio_adapter/channel_close.rb +24 -0
  18. data/examples/coolio_adapter/example_helper.rb +39 -0
  19. data/examples/coolio_adapter/exchange_declare.rb +28 -0
  20. data/examples/coolio_adapter/kitchen_sink1.rb +48 -0
  21. data/examples/coolio_adapter/queue_bind.rb +32 -0
  22. data/examples/coolio_adapter/queue_purge.rb +32 -0
  23. data/examples/coolio_adapter/queue_unbind.rb +37 -0
  24. data/examples/eventmachine_adapter/authentication/plain_password_with_custom_role_credentials.rb +36 -0
  25. data/examples/eventmachine_adapter/authentication/plain_password_with_default_role_credentials.rb +27 -0
  26. data/examples/eventmachine_adapter/authentication/plain_password_with_incorrect_credentials.rb +18 -0
  27. data/examples/eventmachine_adapter/basic_cancel.rb +49 -0
  28. data/examples/eventmachine_adapter/basic_consume.rb +51 -0
  29. data/examples/eventmachine_adapter/basic_consume_with_acknowledgements.rb +45 -0
  30. data/examples/eventmachine_adapter/basic_consume_with_rejections.rb +45 -0
  31. data/examples/eventmachine_adapter/basic_get.rb +57 -0
  32. data/examples/eventmachine_adapter/basic_get_with_empty_queue.rb +53 -0
  33. data/examples/eventmachine_adapter/basic_publish.rb +38 -0
  34. data/examples/eventmachine_adapter/basic_qos.rb +29 -0
  35. data/examples/eventmachine_adapter/basic_recover.rb +29 -0
  36. data/examples/eventmachine_adapter/basic_return.rb +34 -0
  37. data/examples/eventmachine_adapter/channel_close.rb +24 -0
  38. data/examples/eventmachine_adapter/channel_flow.rb +36 -0
  39. data/examples/eventmachine_adapter/channel_level_exception_handling.rb +44 -0
  40. data/examples/eventmachine_adapter/example_helper.rb +39 -0
  41. data/examples/eventmachine_adapter/exchange_declare.rb +54 -0
  42. data/examples/eventmachine_adapter/extensions/rabbitmq/handling_confirm_select_ok.rb +31 -0
  43. data/examples/eventmachine_adapter/extensions/rabbitmq/publisher_confirmations_with_transient_messages.rb +56 -0
  44. data/examples/eventmachine_adapter/extensions/rabbitmq/publisher_confirmations_with_unroutable_message.rb +46 -0
  45. data/examples/eventmachine_adapter/kitchen_sink1.rb +50 -0
  46. data/examples/eventmachine_adapter/queue_bind.rb +32 -0
  47. data/examples/eventmachine_adapter/queue_declare.rb +34 -0
  48. data/examples/eventmachine_adapter/queue_purge.rb +32 -0
  49. data/examples/eventmachine_adapter/queue_unbind.rb +37 -0
  50. data/examples/eventmachine_adapter/tx_commit.rb +29 -0
  51. data/examples/eventmachine_adapter/tx_rollback.rb +29 -0
  52. data/examples/eventmachine_adapter/tx_select.rb +27 -0
  53. data/examples/socket_adapter/basics.rb +19 -0
  54. data/examples/socket_adapter/connection.rb +53 -0
  55. data/examples/socket_adapter/multiple_connections.rb +17 -0
  56. data/irb.rb +66 -0
  57. data/lib/amq/client.rb +15 -0
  58. data/lib/amq/client/adapter.rb +356 -0
  59. data/lib/amq/client/adapters/coolio.rb +221 -0
  60. data/lib/amq/client/adapters/event_machine.rb +228 -0
  61. data/lib/amq/client/adapters/socket.rb +89 -0
  62. data/lib/amq/client/channel.rb +338 -0
  63. data/lib/amq/client/connection.rb +246 -0
  64. data/lib/amq/client/entity.rb +117 -0
  65. data/lib/amq/client/exceptions.rb +86 -0
  66. data/lib/amq/client/exchange.rb +163 -0
  67. data/lib/amq/client/extensions/rabbitmq.rb +5 -0
  68. data/lib/amq/client/extensions/rabbitmq/basic.rb +36 -0
  69. data/lib/amq/client/extensions/rabbitmq/confirm.rb +254 -0
  70. data/lib/amq/client/framing/io/frame.rb +32 -0
  71. data/lib/amq/client/framing/string/frame.rb +62 -0
  72. data/lib/amq/client/logging.rb +56 -0
  73. data/lib/amq/client/mixins/anonymous_entity.rb +21 -0
  74. data/lib/amq/client/mixins/status.rb +62 -0
  75. data/lib/amq/client/protocol/get_response.rb +55 -0
  76. data/lib/amq/client/queue.rb +450 -0
  77. data/lib/amq/client/settings.rb +83 -0
  78. data/lib/amq/client/version.rb +5 -0
  79. data/spec/benchmarks/adapters.rb +77 -0
  80. data/spec/client/framing/io_frame_spec.rb +57 -0
  81. data/spec/client/framing/string_frame_spec.rb +57 -0
  82. data/spec/client/protocol/get_response_spec.rb +79 -0
  83. data/spec/integration/coolio/basic_ack_spec.rb +41 -0
  84. data/spec/integration/coolio/basic_get_spec.rb +73 -0
  85. data/spec/integration/coolio/basic_return_spec.rb +33 -0
  86. data/spec/integration/coolio/channel_close_spec.rb +26 -0
  87. data/spec/integration/coolio/channel_flow_spec.rb +46 -0
  88. data/spec/integration/coolio/spec_helper.rb +31 -0
  89. data/spec/integration/coolio/tx_commit_spec.rb +40 -0
  90. data/spec/integration/coolio/tx_rollback_spec.rb +44 -0
  91. data/spec/integration/eventmachine/basic_ack_spec.rb +40 -0
  92. data/spec/integration/eventmachine/basic_get_spec.rb +73 -0
  93. data/spec/integration/eventmachine/basic_return_spec.rb +35 -0
  94. data/spec/integration/eventmachine/channel_close_spec.rb +26 -0
  95. data/spec/integration/eventmachine/channel_flow_spec.rb +32 -0
  96. data/spec/integration/eventmachine/spec_helper.rb +22 -0
  97. data/spec/integration/eventmachine/tx_commit_spec.rb +47 -0
  98. data/spec/integration/eventmachine/tx_rollback_spec.rb +35 -0
  99. data/spec/regression/bad_frame_slicing_in_adapters_spec.rb +59 -0
  100. data/spec/spec_helper.rb +24 -0
  101. data/spec/unit/client/adapter_spec.rb +49 -0
  102. data/spec/unit/client/entity_spec.rb +49 -0
  103. data/spec/unit/client/logging_spec.rb +60 -0
  104. data/spec/unit/client/mixins/status_spec.rb +72 -0
  105. data/spec/unit/client/settings_spec.rb +27 -0
  106. data/spec/unit/client_spec.rb +11 -0
  107. data/tasks.rb +11 -0
  108. metadata +202 -0
@@ -0,0 +1,338 @@
1
+ # encoding: utf-8
2
+
3
+ require "amq/client/entity"
4
+ require "amq/client/adapter"
5
+
6
+ module AMQ
7
+ module Client
8
+ class Channel < Entity
9
+
10
+ #
11
+ # API
12
+ #
13
+
14
+
15
+ class ChannelOutOfBadError < StandardError # TODO: inherit from some AMQP error class defined in amq-protocol or use it straight away.
16
+ def initialize(max, given)
17
+ super("Channel max is #{max}, #{given} given.")
18
+ end
19
+ end
20
+
21
+
22
+ DEFAULT_REPLY_TEXT = "Goodbye".freeze
23
+
24
+ attr_reader :id
25
+
26
+ attr_reader :exchanges_awaiting_declare_ok, :exchanges_awaiting_delete_ok
27
+ attr_reader :queues_awaiting_declare_ok, :queues_awaiting_delete_ok, :queues_awaiting_bind_ok, :queues_awaiting_unbind_ok, :queues_awaiting_purge_ok, :queues_awaiting_consume_ok, :queues_awaiting_cancel_ok, :queues_awaiting_get_response
28
+
29
+ attr_accessor :flow_is_active
30
+
31
+
32
+ def initialize(client, id)
33
+ super(client)
34
+
35
+ @id = id
36
+ @exchanges = Hash.new
37
+ @queues = Hash.new
38
+ @consumers = Hash.new
39
+
40
+ reset_state!
41
+
42
+ # 65536 is here for cases when channel is opened without passing a callback in,
43
+ # otherwise channel_mix would be nil and it causes a lot of needless headaches.
44
+ # lets just have this default. MK.
45
+ channel_max = client.connection.channel_max || 65536
46
+
47
+ if channel_max != 0 && !(0..channel_max).include?(id)
48
+ raise ChannelOutOfBadError.new(channel_max, id)
49
+ end
50
+ end
51
+
52
+ def consumers
53
+ @consumers
54
+ end # consumers
55
+
56
+ # @return [Array<Queue>] Collection of queues that were declared on this channel.
57
+ def queues
58
+ @queues.values
59
+ end
60
+
61
+ # @return [Array<Exchange>] Collection of exchanges that were declared on this channel.
62
+ def exchanges
63
+ @exchanges.values
64
+ end
65
+
66
+
67
+ # AMQP connection this channel belongs to.
68
+ #
69
+ # @return [AMQ::Client::Connection] Connection this channel belongs to.
70
+ def connection
71
+ @client.connection
72
+ end # connection
73
+
74
+ # Opens AMQP channel.
75
+ #
76
+ # @api public
77
+ def open(&block)
78
+ @client.send Protocol::Channel::Open.encode(@id, AMQ::Protocol::EMPTY_STRING)
79
+ @client.connection.channels[@id] = self
80
+ self.status = :opening
81
+
82
+ self.define_callback :open, &block
83
+ end
84
+
85
+ # Closes AMQP channel.
86
+ #
87
+ # @api public
88
+ def close(reply_code = 200, reply_text = DEFAULT_REPLY_TEXT, class_id = 0, method_id = 0, &block)
89
+ @client.send Protocol::Channel::Close.encode(@id, reply_code, reply_text, class_id, method_id)
90
+
91
+ self.define_callback :close, &block
92
+ end
93
+
94
+
95
+ # Acknowledge one or all messages on the channel.
96
+ #
97
+ # @api public
98
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.13.)
99
+ def acknowledge(delivery_tag, multiple = false)
100
+ @client.send(Protocol::Basic::Ack.encode(self.id, delivery_tag, multiple))
101
+
102
+ self
103
+ end # acknowledge(delivery_tag, multiple = false)
104
+
105
+ # Reject a message with given delivery tag.
106
+ #
107
+ # @api public
108
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.14.)
109
+ def reject(delivery_tag, requeue = true)
110
+ @client.send(Protocol::Basic::Reject.encode(self.id, delivery_tag, requeue))
111
+
112
+ self
113
+ end # reject(delivery_tag, requeue = true)
114
+
115
+ # Requests a specific quality of service. The QoS can be specified for the current channel
116
+ # or for all channels on the connection.
117
+ #
118
+ # @note RabbitMQ as of 2.3.1 does not support prefetch_size.
119
+ # @api public
120
+ def qos(prefetch_size = 0, prefetch_count = 32, global = false, &block)
121
+ @client.send Protocol::Basic::Qos.encode(@id, prefetch_size, prefetch_count, global)
122
+
123
+ self.redefine_callback :qos, &block
124
+ self
125
+ end # qos(prefetch_size = 4096, prefetch_count = 32, global = false, &block)
126
+
127
+ # Notifies AMQ broker that consumer has recovered and unacknowledged messages need
128
+ # to be redelivered.
129
+ #
130
+ # @return [Channel] self
131
+ #
132
+ # @note RabbitMQ as of 2.3.1 does not support basic.recover with requeue = false.
133
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.16.)
134
+ # @api public
135
+ def recover(requeue = true, &block)
136
+ @client.send(Protocol::Basic::Recover.encode(@id, requeue))
137
+
138
+ self.redefine_callback :recover, &block
139
+ self
140
+ end # recover(requeue = false, &block)
141
+
142
+ # Asks the peer to pause or restart the flow of content data sent to a consumer.
143
+ # This is a simple flow­control mechanism that a peer can use to avoid overflowing its
144
+ # queues or otherwise finding itself receiving more messages than it can process. Note that
145
+ # this method is not intended for window control. It does not affect contents returned to
146
+ # Queue#get callers.
147
+ #
148
+ # @param [Boolean] Desired flow state.
149
+ #
150
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.5.2.3.)
151
+ # @api public
152
+ def flow(active = false, &block)
153
+ @client.send Protocol::Channel::Flow.encode(@id, active)
154
+
155
+ self.redefine_callback :flow, &block
156
+ self
157
+ end # flow(active = false, &block)
158
+
159
+
160
+ # Sets the channel to use standard transactions. One must use this method at least
161
+ # once on a channel before using #tx_tommit or tx_rollback methods.
162
+ #
163
+ # @api public
164
+ def tx_select(&block)
165
+ @client.send Protocol::Tx::Select.encode(@id)
166
+
167
+ self.redefine_callback :tx_select, &block
168
+ self
169
+ end # tx_select(&block)
170
+
171
+ # Commits AMQP transaction.
172
+ #
173
+ # @api public
174
+ def tx_commit(&block)
175
+ @client.send Protocol::Tx::Commit.encode(@id)
176
+
177
+ self.redefine_callback :tx_commit, &block
178
+ self
179
+ end # tx_commit(&block)
180
+
181
+ # Rolls AMQP transaction back.
182
+ #
183
+ # @api public
184
+ def tx_rollback(&block)
185
+ @client.send Protocol::Tx::Rollback.encode(@id)
186
+
187
+ self.redefine_callback :tx_rollback, &block
188
+ self
189
+ end # tx_rollback(&block)
190
+
191
+ # @return [Boolean] True if flow in this channel is active (messages will be delivered to consumers that use this channel).
192
+ #
193
+ # @api public
194
+ def flow_is_active?
195
+ @flow_is_active
196
+ end # flow_is_active?
197
+
198
+ def on_error(&block)
199
+ self.define_callback(:close, &block)
200
+ end
201
+
202
+
203
+ #
204
+ # Implementation
205
+ #
206
+
207
+ def register_exchange(exchange)
208
+ raise ArgumentError, "argument is nil!" if exchange.nil?
209
+
210
+ @exchanges[exchange.name] = exchange
211
+ end # register_exchange(exchange)
212
+
213
+ def find_exchange(name)
214
+ @exchanges[name]
215
+ end
216
+
217
+ def register_queue(queue)
218
+ raise ArgumentError, "argument is nil!" if queue.nil?
219
+
220
+ @queues[queue.name] = queue
221
+ end # register_queue(queue)
222
+
223
+ def find_queue(name)
224
+ @queues[name]
225
+ end
226
+
227
+
228
+ def reset_state!
229
+ @flow_is_active = true
230
+
231
+ @queues_awaiting_declare_ok = Array.new
232
+ @exchanges_awaiting_declare_ok = Array.new
233
+
234
+ @queues_awaiting_delete_ok = Array.new
235
+
236
+ @exchanges_awaiting_delete_ok = Array.new
237
+ @queues_awaiting_purge_ok = Array.new
238
+ @queues_awaiting_bind_ok = Array.new
239
+ @queues_awaiting_unbind_ok = Array.new
240
+ @queues_awaiting_consume_ok = Array.new
241
+ @queues_awaiting_cancel_ok = Array.new
242
+
243
+ @queues_awaiting_get_response = Array.new
244
+ end # reset_state!
245
+
246
+
247
+ def on_connection_interruption(exception = nil)
248
+ self.reset_state!
249
+ end # on_connection_interruption
250
+
251
+ def handle_open_ok(method)
252
+ self.status = :opened
253
+ self.exec_callback_once_yielding_self(:open, method)
254
+ end
255
+
256
+ def handle_close_ok(method)
257
+ self.status = :closed
258
+ self.exec_callback_once_yielding_self(:close, method)
259
+ end
260
+
261
+ def handle_close(method, exception = nil)
262
+ puts "In Channel#handle_close"
263
+ self.status = :closed
264
+ self.exec_callback_once_yielding_self(:close, method)
265
+
266
+ self.on_connection_interruption(exception)
267
+ end
268
+
269
+ # === Handlers ===
270
+
271
+ self.handle(Protocol::Channel::OpenOk) do |client, frame|
272
+ channel = client.connection.channels[frame.channel]
273
+ channel.handle_open_ok(frame.decode_payload)
274
+ end
275
+
276
+ self.handle(Protocol::Channel::CloseOk) do |client, frame|
277
+ method = frame.decode_payload
278
+ channels = client.connection.channels
279
+
280
+ channel = channels[frame.channel]
281
+ channels.delete(channel)
282
+
283
+ channel.handle_close_ok(method)
284
+ end
285
+
286
+ self.handle(Protocol::Channel::Close) do |client, frame|
287
+ exception = nil
288
+
289
+ begin
290
+ method = frame.decode_payload
291
+ rescue AMQ::Protocol::Error => e
292
+ exception = e
293
+ end
294
+ channels = client.connection.channels
295
+ channel = channels[frame.channel]
296
+
297
+ if exception
298
+ channel.handle_close(method, exception)
299
+ else
300
+ channel.handle_close(method)
301
+ end
302
+ end
303
+
304
+ self.handle(Protocol::Basic::QosOk) do |client, frame|
305
+ channel = client.connection.channels[frame.channel]
306
+ channel.exec_callback(:qos, frame.decode_payload)
307
+ end
308
+
309
+ self.handle(Protocol::Basic::RecoverOk) do |client, frame|
310
+ channel = client.connection.channels[frame.channel]
311
+ channel.exec_callback(:recover, frame.decode_payload)
312
+ end
313
+
314
+ self.handle(Protocol::Channel::FlowOk) do |client, frame|
315
+ channel = client.connection.channels[frame.channel]
316
+ method = frame.decode_payload
317
+
318
+ channel.flow_is_active = method.active
319
+ channel.exec_callback(:flow, method)
320
+ end
321
+
322
+ self.handle(Protocol::Tx::SelectOk) do |client, frame|
323
+ channel = client.connection.channels[frame.channel]
324
+ channel.exec_callback(:tx_select, frame.decode_payload)
325
+ end
326
+
327
+ self.handle(Protocol::Tx::CommitOk) do |client, frame|
328
+ channel = client.connection.channels[frame.channel]
329
+ channel.exec_callback(:tx_commit, frame.decode_payload)
330
+ end
331
+
332
+ self.handle(Protocol::Tx::RollbackOk) do |client, frame|
333
+ channel = client.connection.channels[frame.channel]
334
+ channel.exec_callback(:tx_rollback, frame.decode_payload)
335
+ end
336
+ end # Channel
337
+ end # Client
338
+ end # AMQ
@@ -0,0 +1,246 @@
1
+ # encoding: utf-8
2
+
3
+ require "amq/client"
4
+ require "amq/client/entity"
5
+
6
+ module AMQ
7
+ module Client
8
+ # AMQP connection object handles various connection lifecycle events
9
+ # (for example, Connection.Start-Ok, Connection.Tune-Ok and Connection.Close
10
+ # methods)
11
+ #
12
+ # AMQP connection has multiple channels accessible via {Connection#channels} reader.
13
+ class Connection < Entity
14
+
15
+ #
16
+ # Behaviors
17
+ #
18
+
19
+ include StatusMixin
20
+
21
+
22
+ #
23
+ # API
24
+ #
25
+
26
+ # TODO: make it possible to override these from, say, amqp gem or bunny
27
+ CLIENT_PROPERTIES = {
28
+ :platform => ::RUBY_DESCRIPTION,
29
+ :product => "AMQ Client",
30
+ :version => AMQ::Client::VERSION,
31
+ :homepage => "https://github.com/ruby-amqp/amq-client"
32
+ }.freeze
33
+
34
+ # Client capabilities
35
+ #
36
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.2.1)
37
+ attr_accessor :client_properties
38
+
39
+ # Server capabilities
40
+ #
41
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.1.3)
42
+ attr_reader :server_properties
43
+
44
+ # Authentication mechanism used.
45
+ #
46
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.2)
47
+ attr_reader :mechanism
48
+
49
+ # Security response data.
50
+ #
51
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Sections 1.4.2.2 and 1.4.2.4.1)
52
+ attr_reader :response
53
+
54
+ # The locale defines the language in which the server will send reply texts.
55
+ #
56
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.2)
57
+ attr_reader :locale
58
+
59
+ # Channels within this connection.
60
+ #
61
+ # @see http://bit.ly/hw2ELX AMQP 0.9.1 specification (Section 2.2.5)
62
+ attr_reader :channels
63
+
64
+ # Maximum channel number that the server permits this connection to use.
65
+ # Usable channel numbers are in the range 1..channel_max.
66
+ # Zero indicates no specified limit.
67
+ #
68
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Sections 1.4.2.5.1 and 1.4.2.6.1)
69
+ attr_accessor :channel_max
70
+
71
+ # Maximum frame size that the server permits this connection to use.
72
+ #
73
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Sections 1.4.2.5.2 and 1.4.2.6.2)
74
+ attr_accessor :frame_max
75
+
76
+ # The delay, in seconds, of the connection heartbeat that the server wants.
77
+ # Zero means the server does not want a heartbeat.
78
+ #
79
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.5.3)
80
+ attr_accessor :heartbeat_interval
81
+
82
+ attr_reader :known_hosts
83
+
84
+
85
+
86
+
87
+ def initialize(client, mechanism, response, locale, client_properties = nil)
88
+ @mechanism = mechanism
89
+ @response = response
90
+ @locale = locale
91
+
92
+ @channels = Hash.new
93
+ @client_properties = client_properties || {
94
+ :platform => "Ruby #{RUBY_VERSION}",
95
+ :product => "AMQ Client",
96
+ :information => "http://github.com/ruby-amqp/amq-client",
97
+ :version => AMQ::Client::VERSION
98
+ }
99
+
100
+ reset_state!
101
+
102
+ super(client)
103
+
104
+ @client.connections.push(self)
105
+
106
+ # Default errback.
107
+ # You might want to override it, otherwise it'll
108
+ # crash your program. It's the expected behaviour
109
+ # if it's a synchronous one, but not if you use
110
+ # some kind of event loop like EventMachine etc.
111
+ self.define_callback(:close) { |exception| raise(exception) }
112
+ end
113
+
114
+
115
+ def settings
116
+ @client.settings
117
+ end # settings
118
+
119
+
120
+ #
121
+ # Connection class methods
122
+ #
123
+
124
+
125
+ # Sends connection.open to the server.
126
+ #
127
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.7)
128
+ def open(vhost = "/")
129
+ @client.send Protocol::Connection::Open.encode(vhost)
130
+ end
131
+
132
+
133
+ # Sends connection.close to the server.
134
+ #
135
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.9)
136
+ def close(reply_code = 200, reply_text = "Goodbye", class_id = 0, method_id = 0)
137
+ @client.send Protocol::Connection::Close.encode(reply_code, reply_text, class_id, method_id)
138
+ closing!
139
+ end
140
+
141
+
142
+ def reset_state!
143
+ end # reset_state!
144
+
145
+
146
+
147
+ #
148
+ # Implementation
149
+ #
150
+
151
+
152
+ # Handles connection.open
153
+ #
154
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.1.)
155
+ def start_ok(method)
156
+ @server_properties = method.server_properties
157
+
158
+ # it's not clear whether we should transition to :opening state here
159
+ # or in #open but in case authentication fails, it would be strange to have
160
+ # @status undefined. So lets do this. MK.
161
+ opening!
162
+ @client.send Protocol::Connection::StartOk.encode(@client_properties, @mechanism, @response, @locale)
163
+ end
164
+
165
+
166
+ # Handles connection.open-Ok
167
+ #
168
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.8.)
169
+ def handle_open_ok(method)
170
+ @known_hosts = method.known_hosts
171
+
172
+ opened!
173
+ # async adapters need this callback to proceed with
174
+ # Adapter.connect block evaluation
175
+ @client.connection_successful if @client.respond_to?(:connection_successful)
176
+ end
177
+
178
+ # Handles connection.tune-ok
179
+ #
180
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.6)
181
+ def handle_tune(method)
182
+ @channel_max = method.channel_max
183
+ @frame_max = method.frame_max
184
+ @heartbeat_interval = @client.heartbeat_interval || method.heartbeat
185
+
186
+ @client.send Protocol::Connection::TuneOk.encode(@channel_max, [settings[:frame_max], @frame_max].min, @heartbeat_interval)
187
+ end # handle_tune(method)
188
+
189
+
190
+ # Handles connection.close
191
+ #
192
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.5.2.9)
193
+ def handle_close(method)
194
+ self.channels.each { |key, value| value.on_connection_interruption }
195
+
196
+ closed!
197
+ # TODO: use proper exception class, provide protocol class (we know method.class_id and method.method_id) as well!
198
+ self.error RuntimeError.new(method.reply_text)
199
+ end
200
+
201
+ # Handles connection.close-ok
202
+ #
203
+ # @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.4.2.10)
204
+ def handle_close_ok(method)
205
+ closed!
206
+ @client.disconnection_successful
207
+ end # handle_close_ok(method)
208
+
209
+
210
+ def on_connection_interruption
211
+ @channels.each { |n, c| c.on_connection_interruption }
212
+ end # on_connection_interruption
213
+
214
+
215
+
216
+ #
217
+ # Handlers
218
+ #
219
+
220
+ self.handle(Protocol::Connection::Start) do |client, frame|
221
+ client.connection.start_ok(frame.decode_payload)
222
+ end
223
+
224
+ self.handle(Protocol::Connection::Tune) do |client, frame|
225
+ client.connection.handle_tune(frame.decode_payload)
226
+
227
+ client.connection.open(client.settings[:vhost] || "/")
228
+ client.open_successful
229
+ end
230
+
231
+ self.handle(Protocol::Connection::OpenOk) do |client, frame|
232
+ client.connection.handle_open_ok(frame.decode_payload)
233
+ end
234
+
235
+ self.handle(Protocol::Connection::Close) do |client, frame|
236
+ client.connection.handle_close(frame.decode_payload)
237
+ end
238
+
239
+ self.handle(Protocol::Connection::CloseOk) do |client, frame|
240
+ client.connection.handle_close_ok(frame.decode_payload)
241
+ end
242
+
243
+
244
+ end # Connection
245
+ end # Client
246
+ end # AMQ