amq-client 0.5.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 (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