amq-client 0.7.0.alpha23 → 0.7.0.alpha24

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -27,11 +27,10 @@ conciseness.
27
27
 
28
28
  h2. Adapters
29
29
 
30
- Version 1.0 will feature 3 adapters:
30
+ Currently implemented adapters:
31
31
 
32
- * EventMachine (asynchronous)
33
- * cool.io (asynchronous)
34
- * TCP sockets (synchronous)
32
+ * "EventMachine":http://github.com/eventmachine/eventmachine
33
+ * "cool.io":http://coolio.github.com/
35
34
 
36
35
  h3. EventMachine adapter
37
36
 
@@ -46,11 +45,6 @@ cool.io adapter is on par with EventMachine but is not used by any popular libra
46
45
  Note that cool.io doesn't work on JRuby and Microsoft Windows(tm).
47
46
 
48
47
 
49
- h3. TCP socket adapter
50
-
51
- TCP socket adapter is largely incomplete.
52
-
53
-
54
48
  h2. Installation
55
49
 
56
50
  amq-client is available from rubygems.org:
data/lib/amq/client.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "amq/client/version"
4
4
  require "amq/client/exceptions"
5
+ require "amq/client/handlers_registry"
5
6
  require "amq/client/adapter"
6
7
  require "amq/client/channel"
7
8
  require "amq/client/exchange"
@@ -23,8 +24,8 @@ module AMQ
23
24
  # where metadata are hash with :path and :const_name keys.
24
25
  #
25
26
  # @example
26
- # AMQ::Client.adapters[:socket]
27
- # # => {path: full_path, const_name: "SocketClient"}}
27
+ # AMQ::Client.adapters[:event_machine] # => {path: "...", const_name: "EventMachineClient"}}
28
+ #
28
29
  # @return [Hash]
29
30
  # @api public
30
31
  def self.adapters
@@ -50,7 +51,7 @@ module AMQ
50
51
  # @param [Hash] Connection parameters, including :adapter to use.
51
52
  # @api public
52
53
  def self.connect(settings = nil, &block)
53
- adapter = (settings && settings.delete(:adapter)) || :socket
54
+ adapter = (settings && settings.delete(:adapter))
54
55
  adapter = load_adapter(adapter)
55
56
  adapter.connect(settings, &block)
56
57
  end
@@ -66,5 +67,5 @@ module AMQ
66
67
  rescue LoadError
67
68
  raise InvalidAdapterNameError.new(adapter)
68
69
  end
69
- end
70
- end
70
+ end # Client
71
+ end # AMQ
@@ -16,29 +16,6 @@ module AMQ
16
16
  # * #estabilish_connection(settings)
17
17
  # * #close_connection
18
18
  #
19
- # Adapters also must indicate whether they operate in asynchronous or synchronous mode
20
- # using AMQ::Client::Adapter.sync accessor:
21
- #
22
- # @example EventMachine adapter indicates that it is asynchronous
23
- # module AMQ
24
- # module Client
25
- # class EventMachineClient
26
- #
27
- # #
28
- # # Behaviors
29
- # #
30
- #
31
- # include AMQ::Client::Adapter
32
- # include EventMachine::Deferrable
33
- #
34
- # self.sync = false
35
- #
36
- # # the rest of implementation code ...
37
- #
38
- # end
39
- # end
40
- # end
41
- #
42
19
  # @abstract
43
20
  module Adapter
44
21
 
@@ -126,27 +103,6 @@ module AMQ
126
103
  instance
127
104
  end
128
105
 
129
- # @see AMQ::Client::Adapter
130
- def sync=(boolean)
131
- @sync = boolean
132
- end
133
-
134
- # Use this method to detect whether adapter is synchronous or asynchronous.
135
- #
136
- # @return [Boolean] true if this adapter is synchronous
137
- # @api plugin
138
- # @see AMQ::Client::Adapter
139
- def sync?
140
- @sync == true
141
- end
142
-
143
- # @see #sync?
144
- # @api plugin
145
- # @see AMQ::Client::Adapter
146
- def async?
147
- !sync?
148
- end
149
-
150
106
 
151
107
  # Can be overriden by higher-level libraries like amqp gem or bunny.
152
108
  # Defaults to AMQ::Client::TCPConnectionFailed.
@@ -170,7 +126,7 @@ module AMQ
170
126
  # Behaviors
171
127
  #
172
128
 
173
- include AMQ::Client::StatusMixin
129
+ include AMQ::Client::Openable
174
130
 
175
131
  extend RegisterEntityMixin
176
132
 
@@ -201,10 +157,6 @@ module AMQ
201
157
  def handshake(mechanism = "PLAIN", response = "\0guest\0guest", locale = "en_GB")
202
158
  self.send_preamble
203
159
  self.connection = AMQ::Client::Connection.new(self, mechanism, response, locale)
204
- if self.sync?
205
- self.receive # Start/Start-Ok
206
- self.receive # Tune/Tune-Ok
207
- end
208
160
  end
209
161
 
210
162
  # Properly close connection with AMQ broker, as described in
@@ -279,7 +231,7 @@ module AMQ
279
231
  if Protocol::HeartbeatFrame === frame
280
232
  @last_server_heartbeat = Time.now
281
233
  else
282
- callable = AMQ::Client::Entity.handlers[frame.method_class]
234
+ callable = AMQ::Client::HandlersRegistry.find(frame.method_class)
283
235
  if callable
284
236
  callable.call(self, frames.first, frames[1..-1])
285
237
  else
@@ -299,20 +251,6 @@ module AMQ
299
251
  end # send_heartbeat
300
252
 
301
253
 
302
- # @see .sync?
303
- # @api plugin
304
- # @see AMQ::Client::Adapter
305
- def sync?
306
- self.class.sync?
307
- end
308
-
309
- # @see .async?
310
- # @api plugin
311
- # @see AMQ::Client::Adapter
312
- def async?
313
- self.class.async?
314
- end
315
-
316
254
  # Returns heartbeat interval this client uses, in seconds.
317
255
  # This value may or may not be used depending on broker capabilities.
318
256
  #
@@ -78,9 +78,8 @@ module AMQ
78
78
  #
79
79
 
80
80
  include AMQ::Client::Adapter
81
- include AMQ::Client::CallbacksMixin
81
+ include AMQ::Client::Callbacks
82
82
 
83
- self.sync = false
84
83
 
85
84
  #
86
85
  # API
@@ -18,7 +18,6 @@ module AMQ
18
18
 
19
19
  include AMQ::Client::Adapter
20
20
 
21
- self.sync = false
22
21
 
23
22
  #
24
23
  # API
@@ -119,7 +118,7 @@ module AMQ
119
118
 
120
119
  def initialize(*args)
121
120
  super(*args)
122
-
121
+ opening!
123
122
  @connections = Array.new
124
123
  # track TCP connection state, used to detect initial TCP connection failures.
125
124
  @tcp_connection_established = false
@@ -250,11 +249,7 @@ module AMQ
250
249
  # in the authentication stage. If so, it is likely to signal an authentication
251
250
  # issue. Java client behaves the same way. MK.
252
251
  if authenticating? && !@intentionally_closing_connection
253
- if sync?
254
- raise PossibleAuthenticationFailureError.new(@settings)
255
- else
256
- @on_possible_authentication_failure.call(@settings) if @on_possible_authentication_failure
257
- end
252
+ @on_possible_authentication_failure.call(@settings) if @on_possible_authentication_failure
258
253
  end
259
254
  end # unbind
260
255
 
@@ -0,0 +1,60 @@
1
+ module AMQ
2
+ module Client
3
+ module Callbacks
4
+
5
+ def redefine_callback(event, callable = nil, &block)
6
+ f = (callable || block)
7
+ # yes, re-assign!
8
+ @callbacks[event] = [f]
9
+
10
+ self
11
+ end
12
+
13
+ def define_callback(event, callable = nil, &block)
14
+ f = (callable || block)
15
+
16
+ @callbacks[event] ||= []
17
+ @callbacks[event] << f if f
18
+
19
+ self
20
+ end # define_callback(event, &block)
21
+ alias append_callback define_callback
22
+
23
+ def prepend_callback(event, &block)
24
+ @callbacks[event] ||= []
25
+ @callbacks[event].unshift(block)
26
+
27
+ self
28
+ end # prepend_callback(event, &block)
29
+
30
+ def clear_callbacks(event)
31
+ @callbacks[event].clear if @callbacks[event]
32
+ end # clear_callbacks(event)
33
+
34
+
35
+ def exec_callback(name, *args, &block)
36
+ callbacks = Array(self.callbacks[name])
37
+ callbacks.map { |c| c.call(*args, &block) } if callbacks.any?
38
+ end
39
+
40
+ def exec_callback_once(name, *args, &block)
41
+ callbacks = Array(self.callbacks.delete(name))
42
+ callbacks.map { |c| c.call(*args, &block) } if callbacks.any?
43
+ end
44
+
45
+ def exec_callback_yielding_self(name, *args, &block)
46
+ callbacks = Array(self.callbacks[name])
47
+ callbacks.map { |c| c.call(self, *args, &block) } if callbacks.any?
48
+ end
49
+
50
+ def exec_callback_once_yielding_self(name, *args, &block)
51
+ callbacks = Array(self.callbacks.delete(name))
52
+ callbacks.map { |c| c.call(self, *args, &block) } if callbacks.any?
53
+ end
54
+
55
+ def has_callback?(name)
56
+ self.callbacks[name] && !self.callbacks[name].empty?
57
+ end # has_callback?
58
+ end # Callbacks
59
+ end # Client
60
+ end # AMQ
@@ -6,12 +6,16 @@ require "amq/client/exchange"
6
6
 
7
7
  module AMQ
8
8
  module Client
9
- class Channel < Entity
9
+ class Channel
10
10
 
11
11
  #
12
12
  # Behaviors
13
13
  #
14
14
 
15
+ extend RegisterEntityMixin
16
+ include Entity
17
+ extend ProtocolMethodHandlers
18
+
15
19
  register_entity :queue, AMQ::Client::Queue
16
20
  register_entity :exchange, AMQ::Client::Exchange
17
21
 
@@ -10,26 +10,26 @@ module AMQ
10
10
  # methods)
11
11
  #
12
12
  # AMQP connection has multiple channels accessible via {Connection#channels} reader.
13
- class Connection < Entity
13
+ class Connection
14
14
 
15
15
  #
16
16
  # Behaviors
17
17
  #
18
18
 
19
- include StatusMixin
20
-
19
+ include Entity
20
+ extend ProtocolMethodHandlers
21
21
 
22
22
  #
23
23
  # API
24
24
  #
25
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
26
+ DEFAULT_CLIENT_PROPERTIES = {
27
+ :platform => ::RUBY_DESCRIPTION,
28
+ :product => "AMQ Client",
29
+ :information => "http://github.com/ruby-amqp/amq-client",
30
+ :version => AMQ::Client::VERSION
31
+ }
32
+
33
33
 
34
34
  # Client capabilities
35
35
  #
@@ -84,18 +84,13 @@ module AMQ
84
84
 
85
85
 
86
86
  # @api public
87
- def initialize(client, mechanism, response, locale, client_properties = nil)
87
+ def initialize(client, mechanism, response, locale, client_properties = {})
88
88
  @mechanism = mechanism
89
89
  @response = response
90
90
  @locale = locale
91
91
 
92
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
- }
93
+ @client_properties = DEFAULT_CLIENT_PROPERTIES.merge(client_properties)
99
94
 
100
95
  reset_state!
101
96
 
@@ -106,8 +101,6 @@ module AMQ
106
101
  # Default errback.
107
102
  # You might want to override it, otherwise it'll
108
103
  # 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
104
  self.define_callback(:close) { |exception| raise(exception) }
112
105
  end
113
106
 
@@ -117,6 +110,7 @@ module AMQ
117
110
  end # settings
118
111
 
119
112
 
113
+
120
114
  #
121
115
  # Connection class methods
122
116
  #
@@ -175,8 +169,6 @@ module AMQ
175
169
  @known_hosts = method.known_hosts
176
170
 
177
171
  opened!
178
- # async adapters need this callback to proceed with
179
- # Adapter.connect block evaluation
180
172
  @client.connection_successful if @client.respond_to?(:connection_successful)
181
173
  end
182
174
 
@@ -1,6 +1,7 @@
1
1
  # encoding: utf-8
2
2
 
3
- require "amq/client/mixins/status"
3
+ require "amq/client/callbacks"
4
+ require "amq/client/openable"
4
5
 
5
6
  module AMQ
6
7
  module Client
@@ -14,65 +15,20 @@ module AMQ
14
15
  def register_entity(name, klass)
15
16
  define_method(name) do |*args, &block|
16
17
  klass.new(self, *args, &block)
17
- end
18
- end
19
- end
20
-
21
- module CallbacksMixin
22
- def redefine_callback(event, callable = nil, &block)
23
- f = (callable || block)
24
- # yes, re-assign!
25
- @callbacks[event] = [f]
18
+ end # define_method
19
+ end # register_entity
20
+ end # RegisterEntityMixin
26
21
 
27
- self
22
+ module ProtocolMethodHandlers
23
+ def handle(klass, &block)
24
+ AMQ::Client::HandlersRegistry.register(klass, &block)
28
25
  end
29
26
 
30
- def define_callback(event, callable = nil, &block)
31
- f = (callable || block)
32
-
33
- @callbacks[event] ||= []
34
- @callbacks[event] << f if f
35
-
36
- self
37
- end # define_callback(event, &block)
38
- alias append_callback define_callback
39
-
40
- def prepend_callback(event, &block)
41
- @callbacks[event] ||= []
42
- @callbacks[event].unshift(block)
43
-
44
- self
45
- end # prepend_callback(event, &block)
46
-
47
- def clear_callbacks(event)
48
- @callbacks[event].clear if @callbacks[event]
49
- end # clear_callbacks(event)
50
-
51
-
52
- def exec_callback(name, *args, &block)
53
- callbacks = Array(self.callbacks[name])
54
- callbacks.map { |c| c.call(*args, &block) } if callbacks.any?
27
+ def handlers
28
+ AMQ::Client::HandlersRegistry.handlers
55
29
  end
30
+ end # ProtocolMethodHandlers
56
31
 
57
- def exec_callback_once(name, *args, &block)
58
- callbacks = Array(self.callbacks.delete(name))
59
- callbacks.map { |c| c.call(*args, &block) } if callbacks.any?
60
- end
61
-
62
- def exec_callback_yielding_self(name, *args, &block)
63
- callbacks = Array(self.callbacks[name])
64
- callbacks.map { |c| c.call(self, *args, &block) } if callbacks.any?
65
- end
66
-
67
- def exec_callback_once_yielding_self(name, *args, &block)
68
- callbacks = Array(self.callbacks.delete(name))
69
- callbacks.map { |c| c.call(self, *args, &block) } if callbacks.any?
70
- end
71
-
72
- def has_callback?(name)
73
- self.callbacks[name] && !self.callbacks[name].empty?
74
- end # has_callback?
75
- end
76
32
 
77
33
  # AMQ entities, as implemented by AMQ::Client, have callbacks and can run them
78
34
  # when necessary.
@@ -80,16 +36,14 @@ module AMQ
80
36
  # @note Exchanges and queues implementation is based on this class.
81
37
  #
82
38
  # @abstract
83
- class Entity
39
+ module Entity
84
40
 
85
41
  #
86
42
  # Behaviors
87
43
  #
88
44
 
89
- include StatusMixin
90
- include CallbacksMixin
91
-
92
- extend RegisterEntityMixin
45
+ include Openable
46
+ include Callbacks
93
47
 
94
48
  #
95
49
  # API
@@ -98,16 +52,6 @@ module AMQ
98
52
  # @return [Array<#call>]
99
53
  attr_reader :callbacks
100
54
 
101
- @@handlers ||= Hash.new
102
-
103
- def self.handle(klass, &block)
104
- @@handlers[klass] = block
105
- end
106
-
107
- def self.handlers
108
- @@handlers
109
- end
110
-
111
55
 
112
56
  def initialize(client)
113
57
  @client = client
@@ -118,18 +62,12 @@ module AMQ
118
62
 
119
63
 
120
64
  def error(exception)
121
- if client.sync? # DO NOT DO THIS, just add a default errback to do exactly this, so if someone wants to use begin/rescue, he'll just ignore the errbacks.
122
- # Synchronous error handling.
123
- # Just use begin/rescue in the main loop.
124
- raise exception
125
- else
126
- # Asynchronous error handling.
127
- # Set callback for given class (Queue for example)
128
- # or for the Connection class (or instance, of course).
129
- callbacks = [self.callbacks[:close], self.client.connection.callbacks[:close]].flatten.compact
65
+ # Asynchronous error handling.
66
+ # Set callback for given class (Queue for example)
67
+ # or for the Connection class (or instance, of course).
68
+ callbacks = [self.callbacks[:close], self.client.connection.callbacks[:close]].flatten.compact
130
69
 
131
- callbacks.map { |c| c.call(exception) } if callbacks.any?
132
- end
70
+ callbacks.map { |c| c.call(exception) } if callbacks.any?
133
71
  end
134
72
  end
135
73
  end
@@ -1,18 +1,22 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require "amq/client/entity"
4
- require "amq/client/mixins/anonymous_entity"
4
+ require "amq/client/server_named_entity"
5
5
 
6
6
  module AMQ
7
7
  module Client
8
- class Exchange < Entity
9
- include AnonymousEntityMixin
8
+ class Exchange
9
+
10
+
11
+ include Entity
12
+ include ServerNamedEntity
13
+ extend ProtocolMethodHandlers
10
14
 
11
15
  TYPES = [:fanout, :direct, :topic, :headers].freeze
12
16
 
13
17
  class IncompatibleExchangeTypeError < StandardError
14
18
  def initialize(types, given)
15
- super("Exchange types are #{TYPES.inspect}, #{given.inspect} given.")
19
+ super("#{given.inspect} exchange type is unknown. Standard types are #{TYPES.inspect}, custom exchange types must begin with x-, for example: x-recent-history")
16
20
  end
17
21
  end
18
22
 
@@ -31,7 +35,7 @@ module AMQ
31
35
  attr_reader :type
32
36
 
33
37
  def initialize(client, channel, name, type = :fanout)
34
- unless TYPES.include?(type.to_sym)
38
+ if !(TYPES.include?(type.to_sym) || type.to_s =~ /^x-.+/i)
35
39
  raise IncompatibleExchangeTypeError.new(TYPES, type)
36
40
  end
37
41
 
@@ -71,11 +75,6 @@ module AMQ
71
75
  @channel.exchanges_awaiting_declare_ok.push(self)
72
76
  end
73
77
 
74
-
75
- if @client.sync?
76
- @client.read_until_receives(Protocol::Exchange::DeclareOk) unless nowait
77
- end
78
-
79
78
  self
80
79
  end
81
80
 
@@ -0,0 +1,30 @@
1
+ module AMQ
2
+ module Client
3
+ class HandlersRegistry
4
+
5
+ @@handlers ||= Hash.new
6
+
7
+
8
+ #
9
+ # API
10
+ #
11
+
12
+
13
+ def self.register(klass, &block)
14
+ @@handlers[klass] = block
15
+ end
16
+ class << self
17
+ alias handle register
18
+ end
19
+
20
+ def self.find(klass)
21
+ @@handlers[klass]
22
+ end
23
+
24
+ def self.handlers
25
+ @@handlers
26
+ end
27
+
28
+ end # HandlersRegistry
29
+ end # Client
30
+ end # AMQ
@@ -2,12 +2,12 @@
2
2
 
3
3
  module AMQ
4
4
  module Client
5
- module StatusMixin
5
+ module Openable
6
6
  VALUES = [:opened, :closed, :opening, :closing].freeze
7
7
 
8
8
  class ImproperStatusError < ArgumentError
9
9
  def initialize(value)
10
- super("Value #{value.inspect} isn't permitted. Choose one of: #{AMQ::Client::StatusMixin::VALUES.inspect}")
10
+ super("Value #{value.inspect} isn't permitted. Choose one of: #{AMQ::Client::Openable::VALUES.inspect}")
11
11
  end
12
12
  end
13
13
 
@@ -2,18 +2,20 @@
2
2
 
3
3
  require "amq/client/entity"
4
4
  require "amq/client/adapter"
5
- require "amq/client/mixins/anonymous_entity"
6
- require "amq/client/protocol/get_response"
5
+ require "amq/client/server_named_entity"
6
+ require "amq/protocol/get_response"
7
7
 
8
8
  module AMQ
9
9
  module Client
10
- class Queue < Entity
10
+ class Queue
11
11
 
12
12
  #
13
13
  # Behaviors
14
14
  #
15
15
 
16
- include AnonymousEntityMixin
16
+ include Entity
17
+ include ServerNamedEntity
18
+ extend ProtocolMethodHandlers
17
19
 
18
20
 
19
21
  #
@@ -92,10 +94,6 @@ module AMQ
92
94
  @channel.queues_awaiting_declare_ok.push(self)
93
95
  end
94
96
 
95
- if @client.sync?
96
- @client.read_until_receives(Protocol::Queue::DeclareOk) unless nowait
97
- end
98
-
99
97
  self
100
98
  end
101
99
 
@@ -3,19 +3,21 @@
3
3
  module AMQ
4
4
  module Client
5
5
  # Common behavior of AMQ entities that can be either client or server-named, for example, exchanges and queues.
6
- module AnonymousEntityMixin
6
+ module ServerNamedEntity
7
7
 
8
8
  # @return [Boolean] true if this entity is anonymous (server-named)
9
- def anonymous?
9
+ def server_named?
10
10
  @name.nil? or @name.empty?
11
11
  end
12
+ # backwards compabitility. MK.
13
+ alias anonymous? server_named?
12
14
 
13
15
  def dup
14
- if anonymous?
16
+ if server_named?
15
17
  raise RuntimeError.new("You can't clone anonymous queue until it receives back the name in Queue.Declare-Ok response. Move the code with #dup to the callback for the #declare method.") # TODO: that's not true in all cases, imagine the user didn't call #declare yet.
16
18
  end
17
19
  super
18
20
  end
19
- end # AnonymousEntityMixin
21
+ end # ServerNamedEntity
20
22
  end # Client
21
23
  end # AMQ
@@ -1,5 +1,5 @@
1
1
  module AMQ
2
2
  module Client
3
- VERSION = "0.7.0.alpha23"
3
+ VERSION = "0.7.0.alpha24"
4
4
  end
5
5
  end
@@ -3,7 +3,7 @@
3
3
  require "spec_helper"
4
4
 
5
5
  require "amq/protocol/client"
6
- require "amq/client/protocol/get_response"
6
+ require "amq/protocol/get_response"
7
7
  # require "amq/protocol/frame"
8
8
  #
9
9
  # # We have to use Kernel#load so extensions to the
@@ -2,14 +2,45 @@ require 'spec_helper'
2
2
  require 'integration/eventmachine/spec_helper'
3
3
 
4
4
  describe AMQ::Client::EventMachineClient, "Exchange.Declare" do
5
+
6
+ #
7
+ # Environment
8
+ #
9
+
5
10
  include EventedSpec::SpecHelper
6
11
  default_timeout 1
7
12
  let(:exchange_name) { "amq-client.testexchange.#{Time.now.to_i}" }
13
+
14
+
15
+
16
+ #
17
+ # Examples
18
+ #
19
+
20
+ context "when exchange type is non-standard" do
21
+ context "and DOES NOT begin with x-" do
22
+ it "raises an exception" do
23
+ em_amqp_connect do |client|
24
+ channel = AMQ::Client::Channel.new(client, 1)
25
+ channel.open do
26
+ begin
27
+ AMQ::Client::Exchange.new(client, channel, exchange_name, "my_shiny_metal_exchange_type")
28
+ rescue AMQ::Client::Exchange::IncompatibleExchangeTypeError => e
29
+ done
30
+ end
31
+ end # channel.open
32
+ end # em_amqp_connect
33
+ end # it
34
+ end # context
35
+ end # context
36
+
37
+
38
+
8
39
  it "should create an exchange and trigger a callback" do
9
40
  em_amqp_connect do |client|
10
41
  channel = AMQ::Client::Channel.new(client, 1)
11
42
  channel.open do
12
- exchange = AMQ::Client::Exchange.new(client, channel, exchange_name, :fanout)
43
+ exchange = AMQ::Client::Exchange.new(client, channel, exchange_name, "fanout")
13
44
  exchange.declare do
14
45
  exchange.delete
15
46
  done(0.2)
@@ -4,8 +4,15 @@ require "spec_helper"
4
4
  require "amq/client/entity"
5
5
 
6
6
  describe AMQ::Client::Entity do
7
+ let(:klazz) do
8
+ Class.new do
9
+ include AMQ::Client::Entity
10
+ end
11
+ end
12
+
13
+
7
14
  subject do
8
- AMQ::Client::Entity.new(Object.new)
15
+ klazz.new(Object.new)
9
16
  end
10
17
 
11
18
  it "should maintain an associative array of callbacks" do
@@ -1,11 +1,11 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  require "spec_helper"
4
- require "amq/client/mixins/status"
4
+ require "amq/client/openable"
5
5
 
6
- describe AMQ::Client::StatusMixin do
6
+ describe AMQ::Client::Openable do
7
7
  subject do
8
- Class.new { include AMQ::Client::StatusMixin }.new
8
+ Class.new { include AMQ::Client::Openable }.new
9
9
  end
10
10
 
11
11
  describe "#status=" do
@@ -17,7 +17,7 @@ describe AMQ::Client::StatusMixin do
17
17
 
18
18
  context "when given value isn't in the permitted values" do
19
19
  it "should raise ImproperStatusError" do
20
- lambda { subject.status = :sleepy }.should raise_error(AMQ::Client::StatusMixin::ImproperStatusError)
20
+ lambda { subject.status = :sleepy }.should raise_error(AMQ::Client::Openable::ImproperStatusError)
21
21
  end
22
22
  end
23
23
  end
@@ -7,14 +7,12 @@ require "amq/client"
7
7
  describe AMQ::Client do
8
8
  if RUBY_PLATFORM =~ /java/
9
9
  ADAPTERS = {
10
- :event_machine => "EventMachineClient",
11
- :socket => "SocketClient"
10
+ :event_machine => "EventMachineClient"
12
11
  }
13
12
  else
14
13
  ADAPTERS = {
15
14
  :event_machine => "EventMachineClient",
16
- :coolio => "CoolioClient",
17
- :socket => "SocketClient"
15
+ :coolio => "CoolioClient"
18
16
  }
19
17
  end
20
18
 
@@ -29,7 +27,7 @@ describe AMQ::Client do
29
27
  end
30
28
 
31
29
  it "should provide info about path to the adapter" do
32
- lambda { require @meta[:path] }.should_not raise_error
30
+ require @meta[:path]
33
31
  end
34
32
 
35
33
  it "should provide info about const_name" do
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: amq-client
3
3
  version: !ruby/object:Gem::Version
4
- hash: -3702664446
4
+ hash: -3702664420
5
5
  prerelease: 6
6
6
  segments:
7
7
  - 0
8
8
  - 7
9
9
  - 0
10
10
  - alpha
11
- - 23
12
- version: 0.7.0.alpha23
11
+ - 24
12
+ version: 0.7.0.alpha24
13
13
  platform: ruby
14
14
  authors:
15
15
  - Jakub Stastny
@@ -20,7 +20,7 @@ autorequire:
20
20
  bindir: bin
21
21
  cert_chain: []
22
22
 
23
- date: 2011-05-14 00:00:00 Z
23
+ date: 2011-05-17 00:00:00 Z
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: eventmachine
@@ -127,9 +127,6 @@ files:
127
127
  - examples/eventmachine_adapter/tx_commit.rb
128
128
  - examples/eventmachine_adapter/tx_rollback.rb
129
129
  - examples/eventmachine_adapter/tx_select.rb
130
- - examples/socket_adapter/basics.rb
131
- - examples/socket_adapter/connection.rb
132
- - examples/socket_adapter/multiple_connections.rb
133
130
  - examples/tls_certificates/client/cert.pem
134
131
  - examples/tls_certificates/client/key.pem
135
132
  - examples/tls_certificates/client/keycert.p12
@@ -155,7 +152,7 @@ files:
155
152
  - lib/amq/client/adapter.rb
156
153
  - lib/amq/client/adapters/coolio.rb
157
154
  - lib/amq/client/adapters/event_machine.rb
158
- - lib/amq/client/adapters/socket.rb
155
+ - lib/amq/client/callbacks.rb
159
156
  - lib/amq/client/channel.rb
160
157
  - lib/amq/client/connection.rb
161
158
  - lib/amq/client/entity.rb
@@ -166,13 +163,14 @@ files:
166
163
  - lib/amq/client/extensions/rabbitmq/confirm.rb
167
164
  - lib/amq/client/framing/io/frame.rb
168
165
  - lib/amq/client/framing/string/frame.rb
166
+ - lib/amq/client/handlers_registry.rb
169
167
  - lib/amq/client/logging.rb
170
- - lib/amq/client/mixins/anonymous_entity.rb
171
- - lib/amq/client/mixins/status.rb
172
- - lib/amq/client/protocol/get_response.rb
168
+ - lib/amq/client/openable.rb
173
169
  - lib/amq/client/queue.rb
170
+ - lib/amq/client/server_named_entity.rb
174
171
  - lib/amq/client/settings.rb
175
172
  - lib/amq/client/version.rb
173
+ - lib/amq/protocol/get_response.rb
176
174
  - spec/benchmarks/adapters.rb
177
175
  - spec/client/framing/io_frame_spec.rb
178
176
  - spec/client/framing/string_frame_spec.rb
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- require "bundler"
5
-
6
- Bundler.setup
7
- Bundler.require(:default)
8
-
9
- $LOAD_PATH.unshift(File.expand_path("../../../lib", __FILE__))
10
-
11
- require "amq/client/adapters/socket"
12
-
13
- AMQ::Client::SocketClient.connect(:host => "localhost") do |client|
14
- # Socket API is synchronous, so we don't need any callback here:
15
- tasks = client.queue("tasks", 1)
16
- tasks.consume do |headers, message| # TODO: this is async, we need to use a loop
17
- puts ""
18
- end
19
- end
@@ -1,53 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- require "bundler"
5
-
6
- Bundler.setup
7
- Bundler.require(:default)
8
-
9
- $LOAD_PATH.unshift(File.expand_path("../../../lib", __FILE__))
10
-
11
- require "amq/client/adapters/socket"
12
- require "amq/client/amqp/queue"
13
- require "amq/client/amqp/exchange"
14
-
15
- AMQ::Client::SocketClient.connect(:port => 5672) do |client|
16
- begin
17
- client.handshake
18
-
19
- # Ruby developers are used to use blocks usually synchronously
20
- # (so they are called +/- immediately), but this is NOT the case!
21
- # We always have to wait for the response from the broker, so think
22
- # about the following blocks are true callbacks as you know them
23
- # from JavaScript (i. e. window.onload = function () {}).
24
-
25
- # The only exception is when you use {nowait: true}, then the
26
- # callback is called immediately.
27
- channel = AMQ::Client::Channel.new(client, 1)
28
- channel.open { puts "Channel #{channel.id} opened!" }
29
-
30
- queue = AMQ::Client::Queue.new(client, "", channel)
31
- queue.declare { puts "Queue #{queue.name.inspect} declared!" }
32
-
33
- exchange = AMQ::Client::Exchange.new(client, "tasks", :fanout, channel)
34
- exchange.declare { puts "Exchange #{exchange.name.inspect} declared!" }
35
-
36
- until client.connection.closed?
37
- client.receive_async
38
- sleep 1
39
- end
40
- rescue Interrupt
41
- warn "Manually interrupted, terminating ..."
42
- rescue Exception => exception
43
- STDERR.puts "\n\e[1;31m[#{exception.class}] #{exception.message}\e[0m"
44
- exception.backtrace.each do |line|
45
- line = "\e[0;36m#{line}\e[0m" if line.match(Regexp::quote(File.basename(__FILE__)))
46
- STDERR.puts " - " + line
47
- end
48
- end
49
- end
50
-
51
- # TODO:
52
- # AMQ::Client.connect(:adapter => :socket)
53
- # Support for frame_max, heartbeat from Connection.Tune
@@ -1,17 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # encoding: utf-8
3
-
4
- # Each connection respond to a TCP connection,
5
- # hence we need to use more client.connect calls.
6
-
7
- Thread.new do
8
- AMQ::Client::SocketClient.connect(:port => 5672) do |client|
9
- # ...
10
- end
11
- end
12
-
13
- Thread.new do
14
- AMQ::Client::SocketClient.connect(:port => 5672) do |client|
15
- # ...
16
- end
17
- end
@@ -1,90 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require "socket"
4
- require "amq/client"
5
- require "amq/client/framing/io/frame"
6
-
7
- module AMQ
8
- module Client
9
- class SocketClient
10
-
11
- #
12
- # Behaviors
13
- #
14
-
15
- include AMQ::Client::Adapter
16
-
17
- self.sync = true
18
-
19
- #
20
- # API
21
- #
22
-
23
- def establish_connection(settings)
24
- # NOTE: this doesn't work with "localhost", I don't know why:
25
- settings[:host] = "127.0.0.1" if settings[:host] == "localhost"
26
- @socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
27
- sockaddr = Socket.pack_sockaddr_in(settings[:port], settings[:host])
28
-
29
- @socket.connect(sockaddr)
30
- rescue Errno::ECONNREFUSED => exception
31
- message = "Don't forget to start an AMQP broker first!\nThe original message: #{exception.message}"
32
- raise exception.class.new(message)
33
- rescue Exception => exception
34
- self.disconnect if self.connected?
35
- raise exception
36
- end
37
-
38
- def register_connection_callback(&block)
39
- if block
40
- block.call(self)
41
- self.disconnect
42
- else
43
- self
44
- end
45
- end
46
-
47
- def connection
48
- @socket
49
- end # connection
50
-
51
- def connected?
52
- @socket && !@socket.closed?
53
- end
54
-
55
- def close_connection
56
- @socket.close
57
- end
58
-
59
- def send_raw(data)
60
- @socket.write(data)
61
- end
62
-
63
- def receive
64
- frame = AMQ::Client::Framing::IO::Frame.decode(@socket)
65
- self.receive_frame(frame)
66
- frame
67
- end
68
-
69
- def receive_async
70
- # NOTE: this might work with Socket#eof? as well, it can be better ...
71
- # self.receive unless @socket.eof?
72
-
73
- @sockets ||= [@socket] # It'll be always only one socket, but we don't want to create many arrays, mind the GC!
74
- array = IO.select(@sockets, nil, nil, nil)
75
- array[0].each do |socket|
76
- res = self.receive
77
- end
78
- res
79
- end
80
-
81
- def read_until_receives(klass)
82
- if self.sync?
83
- until (frame = self.receive) && frame.is_a?(Protocol::MethodFrame) && frame.method_class == klass
84
- sleep 0.1
85
- end
86
- end
87
- end
88
- end
89
- end
90
- end