bunny 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ module Qrack
2
+ # Channel ancestor class
3
+ class Channel
4
+
5
+ attr_accessor :number, :active, :frame_buffer
6
+ attr_reader :client
7
+
8
+ def initialize(client)
9
+ @frame_buffer = []
10
+ @client = client
11
+ @number = client.channels.size
12
+ @active = false
13
+ client.channels[@number] = self
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -1,4 +1,7 @@
1
1
  module Qrack
2
+
3
+ class ClientTimeout < Timeout::Error; end
4
+
2
5
  # Client ancestor class
3
6
  class Client
4
7
 
@@ -6,7 +9,177 @@ module Qrack
6
9
  RETRY_DELAY = 10.0
7
10
 
8
11
  attr_reader :status, :host, :vhost, :port, :logging, :spec, :heartbeat
9
- attr_accessor :channel, :logfile, :exchanges, :queues, :channels, :heartbeat_in, :connecting
12
+ attr_accessor :channel, :logfile, :exchanges, :queues, :channels, :message_in, :message_out,
13
+ :connecting
10
14
 
15
+ def initialize(opts = {})
16
+ @host = opts[:host] || 'localhost'
17
+ @user = opts[:user] || 'guest'
18
+ @pass = opts[:pass] || 'guest'
19
+ @vhost = opts[:vhost] || '/'
20
+ @logfile = opts[:logfile] || nil
21
+ @logging = opts[:logging] || false
22
+ @status = :not_connected
23
+ @frame_max = opts[:frame_max] || 131072
24
+ @channel_max = opts[:channel_max] || 0
25
+ @heartbeat = opts[:heartbeat] || 0
26
+ @logger = nil
27
+ create_logger if @logging
28
+ @message_in = false
29
+ @message_out = false
30
+ @connecting = false
31
+ @channels ||= []
32
+ # Create channel 0
33
+ @channel = create_channel()
34
+ @exchanges ||= {}
35
+ @queues ||= {}
36
+ end
37
+
38
+ =begin rdoc
39
+
40
+ === DESCRIPTION:
41
+
42
+ Closes all active communication channels and connection. If an error occurs a
43
+ _Bunny_::_ProtocolError_ is raised. If successful, _Client_._status_ is set to <tt>:not_connected</tt>.
44
+
45
+ ==== RETURNS:
46
+
47
+ <tt>:not_connected</tt> if successful.
48
+
49
+ =end
50
+
51
+ def close
52
+ # Close all active channels
53
+ channels.each do |c|
54
+ c.close if c.open?
55
+ end
56
+
57
+ # Close connection to AMQP server
58
+ close_connection
59
+
60
+ # Close TCP Socket
61
+ close_socket
62
+ end
63
+
64
+ alias stop close
65
+
66
+ def connected?
67
+ status == :connected
68
+ end
69
+
70
+ def connecting?
71
+ connecting
72
+ end
73
+
74
+ def logging=(bool)
75
+ @logging = bool
76
+ create_logger if @logging
77
+ end
78
+
79
+ def next_payload(options = {})
80
+ next_frame(options).payload
81
+ end
82
+
83
+ alias next_method next_payload
84
+
85
+ def read(*args)
86
+ send_command(:read, *args)
87
+ end
88
+
89
+ =begin rdoc
90
+
91
+ === DESCRIPTION:
92
+
93
+ Checks to see whether or not an undeliverable message has been returned as a result of a publish
94
+ with the <tt>:immediate</tt> or <tt>:mandatory</tt> options.
95
+
96
+ ==== OPTIONS:
97
+
98
+ * <tt>:timeout => number of seconds (default = 0.1) - The method will wait for a return
99
+ message until this timeout interval is reached.
100
+
101
+ ==== RETURNS:
102
+
103
+ <tt>:no_return</tt> if message was not returned before timeout .
104
+ <tt>{:header, :return_details, :payload}</tt> if message is returned. <tt>:return_details</tt> is
105
+ a hash <tt>{:reply_code, :reply_text, :exchange, :routing_key}</tt>.
106
+
107
+ =end
108
+
109
+ def returned_message(opts = {})
110
+ secs = opts[:timeout] || 0.1
111
+ frame = next_frame(:timeout => secs)
112
+
113
+ if frame.is_a?(Symbol)
114
+ return :no_return if frame == :timed_out
115
+ end
116
+
117
+ method = frame.payload
118
+ header = next_payload
119
+ msg = next_payload
120
+ raise Bunny::MessageError, 'unexpected length' if msg.length < header.size
121
+
122
+ # Return the message and related info
123
+ {:header => header, :payload => msg, :return_details => method.arguments}
124
+ end
125
+
126
+ def switch_channel(chann)
127
+ if (0...channels.size).include? chann
128
+ @channel = channels[chann]
129
+ chann
130
+ else
131
+ raise RuntimeError, "Invalid channel number - #{chann}"
132
+ end
133
+ end
134
+
135
+ def write(*args)
136
+ send_command(:write, *args)
137
+ end
138
+
139
+ private
140
+
141
+ def close_socket(reason=nil)
142
+ # Close the socket. The server is not considered dead.
143
+ @socket.close if @socket and not @socket.closed?
144
+ @socket = nil
145
+ @status = :not_connected
146
+ end
147
+
148
+ def create_logger
149
+ @logfile ? @logger = Logger.new("#{logfile}") : @logger = Logger.new(STDOUT)
150
+ @logger.level = Logger::INFO
151
+ @logger.datetime_format = "%Y-%m-%d %H:%M:%S"
152
+ end
153
+
154
+ def send_command(cmd, *args)
155
+ begin
156
+ raise Bunny::ConnectionError, 'No connection - socket has not been created' if !@socket
157
+ @socket.__send__(cmd, *args)
158
+ rescue Errno::EPIPE, IOError => e
159
+ raise Bunny::ServerDownError, e.message
160
+ end
161
+ end
162
+
163
+ def socket
164
+ return @socket if @socket and (@status == :connected) and not @socket.closed?
165
+
166
+ begin
167
+ # Attempt to connect.
168
+ @socket = timeout(CONNECT_TIMEOUT) do
169
+ TCPSocket.new(host, port)
170
+ end
171
+
172
+ if Socket.constants.include? 'TCP_NODELAY'
173
+ @socket.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
174
+ end
175
+ rescue => e
176
+ @status = :not_connected
177
+ raise Bunny::ServerDownError, e.message
178
+ end
179
+
180
+ @socket
181
+ end
182
+
11
183
  end
12
- end
184
+
185
+ end
@@ -7,6 +7,8 @@ require 'transport/buffer08'
7
7
  require 'transport/frame08'
8
8
 
9
9
  require 'qrack/client'
10
+ require 'qrack/channel'
11
+ require 'qrack/queue'
10
12
 
11
13
  module Qrack
12
14
 
@@ -7,6 +7,8 @@ require 'transport/buffer09'
7
7
  require 'transport/frame09'
8
8
 
9
9
  require 'qrack/client'
10
+ require 'qrack/channel'
11
+ require 'qrack/queue'
10
12
 
11
13
  module Qrack
12
14
 
@@ -0,0 +1,53 @@
1
+ module Qrack
2
+
3
+ # Queue ancestor class
4
+ class Queue
5
+
6
+ attr_reader :name, :client
7
+ attr_accessor :delivery_tag
8
+
9
+ =begin rdoc
10
+
11
+ === DESCRIPTION:
12
+
13
+ Returns consumer count from Queue#status.
14
+
15
+ =end
16
+
17
+ def consumer_count
18
+ s = status
19
+ s[:consumer_count]
20
+ end
21
+
22
+ =begin rdoc
23
+
24
+ === DESCRIPTION:
25
+
26
+ Returns message count from Queue#status.
27
+
28
+ =end
29
+
30
+ def message_count
31
+ s = status
32
+ s[:message_count]
33
+ end
34
+
35
+ =begin rdoc
36
+
37
+ === DESCRIPTION:
38
+
39
+ Publishes a message to the queue via the default nameless '' direct exchange.
40
+
41
+ ==== RETURNS:
42
+
43
+ nil
44
+
45
+ =end
46
+
47
+ def publish(data, opts = {})
48
+ exchange.publish(data, opts)
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -115,6 +115,13 @@ describe Bunny do
115
115
  exch = @b.exchange('direct_exchange')
116
116
  exch.publish('This is a published message')
117
117
  end
118
+
119
+ it "should not modify the passed options hash when publishing a message" do
120
+ exch = @b.exchange('direct_exchange')
121
+ opts = {:key => 'a', :persistent => true}
122
+ exch.publish('', opts)
123
+ opts.should == {:key => 'a', :persistent => true}
124
+ end
118
125
 
119
126
  it "should be able to return an undeliverable message" do
120
127
  exch = @b.exchange('')
@@ -136,4 +143,4 @@ describe Bunny do
136
143
  exch.delete(:nowait => true)
137
144
  end
138
145
 
139
- end
146
+ end
@@ -67,6 +67,14 @@ describe Bunny do
67
67
  q.message_count.should == 0
68
68
  end
69
69
 
70
+ it "should be able to pop a message where body length exceeds max frame size" do
71
+ q = @b.queue('test1')
72
+ lg_msg = 'z' * 142000
73
+ q.publish(lg_msg)
74
+ msg = q.pop
75
+ msg.should == lg_msg
76
+ end
77
+
70
78
  it "should be able to be purged to remove all of its messages" do
71
79
  q = @b.queue('test1')
72
80
  5.times {q.publish('This is another test message')}
@@ -82,6 +90,24 @@ describe Bunny do
82
90
  msg = q.pop
83
91
  msg.should == :queue_empty
84
92
  end
93
+
94
+ it "should stop subscription without processing messages if max specified is 0" do
95
+ q = @b.queue('test1')
96
+ 5.times {q.publish('Yet another test message')}
97
+ q.message_count.should == 5
98
+ q.subscribe(:message_max => 0){|msg| x = 1}
99
+ q.message_count.should == 5
100
+ q.unsubscribe.should == :unsubscribe_ok
101
+ q.purge.should == :purge_ok
102
+ end
103
+
104
+ it "should stop subscription after processing number of messages specified > 0" do
105
+ q = @b.queue('test1')
106
+ 5.times {q.publish('Yet another test message')}
107
+ q.message_count.should == 5
108
+ q.subscribe(:message_max => 5){|msg| x = 1}
109
+ q.unsubscribe.should == :unsubscribe_ok
110
+ end
85
111
 
86
112
  it "should be able to be deleted" do
87
113
  q = @b.queue('test1')
@@ -115,6 +115,13 @@ describe Bunny do
115
115
  exch = @b.exchange('direct_exchange')
116
116
  exch.publish('This is a published message')
117
117
  end
118
+
119
+ it "should not modify the passed options hash when publishing a message" do
120
+ exch = @b.exchange('direct_exchange')
121
+ opts = {:key => 'a', :persistent => true}
122
+ exch.publish('', opts)
123
+ opts.should == {:key => 'a', :persistent => true}
124
+ end
118
125
 
119
126
  it "should be able to return an undeliverable message" do
120
127
  exch = @b.exchange('')
@@ -136,4 +143,4 @@ describe Bunny do
136
143
  exch.delete(:nowait => true)
137
144
  end
138
145
 
139
- end
146
+ end
@@ -67,6 +67,14 @@ describe Bunny do
67
67
  q.message_count.should == 0
68
68
  end
69
69
 
70
+ it "should be able to pop a message where body length exceeds max frame size" do
71
+ q = @b.queue('test1')
72
+ lg_msg = 'z' * 142000
73
+ q.publish(lg_msg)
74
+ msg = q.pop
75
+ msg.should == lg_msg
76
+ end
77
+
70
78
  it "should be able to be purged to remove all of its messages" do
71
79
  q = @b.queue('test1')
72
80
  5.times {q.publish('This is another test message')}
@@ -82,6 +90,24 @@ describe Bunny do
82
90
  msg = q.pop
83
91
  msg.should == :queue_empty
84
92
  end
93
+
94
+ it "should stop subscription without processing messages if max specified is 0" do
95
+ q = @b.queue('test1')
96
+ 5.times {q.publish('Yet another test message')}
97
+ q.message_count.should == 5
98
+ q.subscribe(:message_max => 0){|msg| x = 1}
99
+ q.message_count.should == 5
100
+ q.unsubscribe.should == :unsubscribe_ok
101
+ q.purge.should == :purge_ok
102
+ end
103
+
104
+ it "should stop subscription after processing number of messages specified > 0" do
105
+ q = @b.queue('test1')
106
+ 5.times {q.publish('Yet another test message')}
107
+ q.message_count.should == 5
108
+ q.subscribe(:message_max => 5){|msg| x = 1}
109
+ q.unsubscribe.should == :unsubscribe_ok
110
+ end
85
111
 
86
112
  it "should be able to be deleted" do
87
113
  q = @b.queue('test1')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bunny
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Duncan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-17 00:00:00 +01:00
12
+ date: 2009-09-07 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -50,6 +50,8 @@ files:
50
50
  - lib/bunny/queue08.rb
51
51
  - lib/bunny/queue09.rb
52
52
  - lib/qrack/client.rb
53
+ - lib/qrack/channel.rb
54
+ - lib/qrack/queue.rb
53
55
  - lib/qrack/protocol/protocol08.rb
54
56
  - lib/qrack/protocol/protocol09.rb
55
57
  - lib/qrack/protocol/spec08.rb