qpid_messaging 0.16.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 (51) hide show
  1. data/LICENSE +234 -0
  2. data/README.rdoc +46 -0
  3. data/Rakefile +87 -0
  4. data/TODO +7 -0
  5. data/examples/client.rb +50 -0
  6. data/examples/drain.rb +111 -0
  7. data/examples/hello_world.rb +49 -0
  8. data/examples/map_receiver.rb +63 -0
  9. data/examples/map_sender.rb +52 -0
  10. data/examples/server.rb +51 -0
  11. data/examples/spout.rb +126 -0
  12. data/ext/cqpid/cqpid.cpp +9903 -0
  13. data/ext/cqpid/extconf.rb +73 -0
  14. data/features/closing_a_connection.feature +13 -0
  15. data/features/closing_a_session.feature +13 -0
  16. data/features/connecting_to_a_broker.feature +13 -0
  17. data/features/creating_a_receiver.feature +29 -0
  18. data/features/creating_a_sender.feature +25 -0
  19. data/features/creating_a_session.feature +12 -0
  20. data/features/getting_the_connections_authenticated_username.feature +8 -0
  21. data/features/receiving_a_message.feature +28 -0
  22. data/features/sending_a_message.feature +21 -0
  23. data/features/session_returns_its_connection.feature +12 -0
  24. data/features/sessions_have_names.feature +8 -0
  25. data/features/step_definitions/address_steps.rb +24 -0
  26. data/features/step_definitions/connection_steps.rb +93 -0
  27. data/features/step_definitions/receiver_steps.rb +61 -0
  28. data/features/step_definitions/sender_steps.rb +34 -0
  29. data/features/step_definitions/session_steps.rb +99 -0
  30. data/features/support/env.rb +22 -0
  31. data/lib/qpid_messaging.rb +30 -0
  32. data/lib/qpid_messaging/address.rb +187 -0
  33. data/lib/qpid_messaging/connection.rb +162 -0
  34. data/lib/qpid_messaging/duration.rb +95 -0
  35. data/lib/qpid_messaging/encoding.rb +61 -0
  36. data/lib/qpid_messaging/errors.rb +33 -0
  37. data/lib/qpid_messaging/message.rb +368 -0
  38. data/lib/qpid_messaging/receiver.rb +184 -0
  39. data/lib/qpid_messaging/sender.rb +152 -0
  40. data/lib/qpid_messaging/session.rb +269 -0
  41. data/lib/qpid_messaging/version.rb +33 -0
  42. data/spec/qpid/address_spec.rb +87 -0
  43. data/spec/qpid/connection_spec.rb +191 -0
  44. data/spec/qpid/duration_spec.rb +56 -0
  45. data/spec/qpid/encoding_spec.rb +63 -0
  46. data/spec/qpid/message_spec.rb +292 -0
  47. data/spec/qpid/receiver_spec.rb +170 -0
  48. data/spec/qpid/sender_spec.rb +135 -0
  49. data/spec/qpid/session_spec.rb +353 -0
  50. data/spec/spec_helper.rb +20 -0
  51. metadata +106 -0
@@ -0,0 +1,184 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ require 'cqpid'
21
+
22
+ module Qpid
23
+
24
+ module Messaging
25
+
26
+ # Receiver is the entity through which messages are received.
27
+ #
28
+ # An instance of Receiver can only be created using an active (not
29
+ # previously closed) Session.
30
+ #
31
+ # ==== Example
32
+ #
33
+ # conn = Qpid::Messaging::Connection.new :url => "mybroker:5762"
34
+ # conn.open
35
+ # session = conn.create_session
36
+ # receiver = session.create_receiver "my-sender-queue"
37
+ class Receiver
38
+
39
+ def initialize(session, receiver_impl) # :nodoc:
40
+ @session = session
41
+ @receiver_impl = receiver_impl
42
+ end
43
+
44
+ def receiver_impl # :nodoc:
45
+ @receiver_impl
46
+ end
47
+
48
+ # Retrieves a message from the local queue, or waits for up to
49
+ # the duration specified for one to become available.
50
+ #
51
+ # If a block is given, then it will be invaked after the next message
52
+ # is received or the call times out, passing in the message or nil
53
+ # respectively.
54
+ #
55
+ # ==== Options
56
+ # * duration - the timeout to wait (def. Duration::FOREVER)
57
+ #
58
+ # ==== Examples
59
+ #
60
+ # msg = rcvr.get # Uses the default timeout of forever
61
+ #
62
+ # msg = rcvr.get Qpid::Messaging::Duration::IMMEDIATE # returns a message or exits immediately
63
+ #
64
+ # # passes in a block to handle the received message
65
+ # rcvr.get Qpid::Messaging::Duration::SECOND do |message|
66
+ # if message.nil?
67
+ # puts "No message was received."
68
+ # else
69
+ # puts "Received this message: #{message.content}"
70
+ # end
71
+ # end
72
+ def get(duration = Qpid::Messaging::Duration::FOREVER)
73
+ message_impl = @receiver_impl.get duration.duration_impl
74
+ create_message_wrapper message_impl unless message_impl.nil?
75
+ end
76
+
77
+ # Retrieves a message from the receiver's subscription, or waits
78
+ # for up to the duration specified for one to become available.
79
+ #
80
+ # If a block is given, then it will be invaked after the next message
81
+ # is received or the call times out, passing in the message or nil
82
+ # respectively.
83
+ #
84
+ # ==== Options
85
+ # * duration - the timeout to wait (def. Duration::FOREVER)
86
+ #
87
+ # ==== Examples
88
+ #
89
+ # msg = rcvr.fetch # Uses the default timeout of forever
90
+ #
91
+ # msg = rcvr.fetch Qpid::Messaging::Duration::IMMEDIATE # returns a message or exits immediately
92
+ #
93
+ # # passes in a block to handle the received message
94
+ # rcvr.fetch Qpid::Messaging::Duration::SECOND do |message|
95
+ # if message.nil?
96
+ # puts "No message was received."
97
+ # else
98
+ # puts "Received this message: #{message.content}"
99
+ # end
100
+ # end
101
+ def fetch(duration = Qpid::Messaging::Duration::FOREVER)
102
+ message_impl = @receiver_impl.fetch duration.duration_impl
103
+ create_message_wrapper message_impl unless message_impl.nil?
104
+ end
105
+
106
+ # Sets the capacity for this +Receiver+.
107
+ #
108
+ # ==== Options
109
+ #
110
+ # * capacity - the capacity
111
+ #
112
+ # ==== Examples
113
+ #
114
+ # receiver.capacity = 50 # sets the incoming capacity to 50 messages
115
+ #
116
+ def capacity=(capacity); @receiver_impl.setCapacity capacity; end
117
+
118
+ # Returns the capacity.
119
+ #
120
+ #
121
+ # The capacity is the numnber of incoming messages that can be held
122
+ # locally before being fetched.
123
+ #
124
+ # ==== Examples
125
+ #
126
+ # puts "The receiver can hold #{rcv.capacity} messages."
127
+ #
128
+ def capacity; @receiver_impl.getCapacity; end
129
+
130
+ # Returns the number of slots for receiving messages.
131
+ #
132
+ # This differs from +capacity+ in that it is the available slots in
133
+ # the capacity for holding incoming messages, where available <= capacity.
134
+ #
135
+ # ==== Examples
136
+ #
137
+ # puts "You can receive #{rcv.available} messages before blocking."
138
+ #
139
+ def available; @receiver_impl.getAvailable; end
140
+
141
+ # Returns the number of messages that have been received and acknowledged
142
+ # but whose acknowledgements have not been confirmed by the sender.
143
+ #
144
+ # ==== Examples
145
+ #
146
+ # puts "You have #{rcv.unsettled} messages to be confirmed."
147
+ #
148
+ def unsettled; @receiver_impl.getUnsettled; end
149
+
150
+ # Closes this +Receiver+.
151
+ #
152
+ # This does not affect the +Session+.
153
+ def close; @receiver_impl.close; end
154
+
155
+ # Returns whether the receiver is closed.
156
+ #
157
+ # ==== Examples
158
+ #
159
+ # recv.close unless recv.closed?
160
+ #
161
+ def closed?; @receiver_impl.isClosed; end
162
+
163
+ # Returns the name of this +Receiver+.
164
+ #
165
+ # ==== Examples
166
+ #
167
+ # puts "Receiver: #{recv.name}"
168
+ def name; @receiver_impl.getName; end
169
+
170
+ # Returns the Session for this +Receiver+.
171
+ def session; @session; end
172
+
173
+ private
174
+
175
+ def create_message_wrapper message_impl # :nodoc:
176
+ Qpid::Messaging::Message.new(:impl => message_impl)
177
+ end
178
+
179
+ end
180
+
181
+ end
182
+
183
+ end
184
+
@@ -0,0 +1,152 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ module Qpid
21
+
22
+ module Messaging
23
+
24
+ # Sender is the entity through which messages sent.
25
+ #
26
+ # An instance of Sender can only be created using an active (not previously
27
+ # closed) Session.
28
+ #
29
+ # ==== Examples
30
+ #
31
+ # conn = Qpid::Messaging::Connection.new :url => "mybroker:5762"
32
+ # conn.open
33
+ # session = conn.create_session
34
+ # sender = session.create_session "my-sender-queue;{create:always}"
35
+ class Sender
36
+
37
+ def initialize(session, sender_impl) # :nodoc:
38
+ @session = session
39
+ @sender_impl = sender_impl
40
+ end
41
+
42
+ def sender_impl # :nodoc:
43
+ @sender_impl
44
+ end
45
+
46
+ # Sends a message.
47
+ #
48
+ # If a block is given, then it will be invoked after the message
49
+ # is sent.
50
+ #
51
+ # ==== Options
52
+ #
53
+ # * message - The message to send.
54
+ # * :sync - See note below on synching.
55
+ #
56
+ # ==== Synching
57
+ #
58
+ # If :sync => true, then the call will block until the broker confirms
59
+ # receipt of the message. Otherwise it will only block for available
60
+ # capacity; i.e., until pending is equal to capacity.
61
+ #
62
+ # ==== Examples
63
+ #
64
+ # sender.send message do |message|
65
+ # puts "Message sent: #{message.content}"
66
+ # end
67
+ #
68
+ def send(message, args = {}, &block)
69
+ sync = args[:sync] || false
70
+ @sender_impl.send message.message_impl, sync
71
+ block.call message unless block.nil?
72
+ end
73
+
74
+ # Closes this +Sender+.
75
+ #
76
+ # This does not affect the +Session+.
77
+ def close; @sender_impl.close; end
78
+
79
+ # Returns the human-readable name for this +Sender+.
80
+ #
81
+ # ==== Examples
82
+ #
83
+ # puts "Sender: #{sender.name}"
84
+ #
85
+ def name; @sender_impl.getName; end
86
+
87
+ # Sets the capacity for this +Sender+.
88
+ #
89
+ # The capacity is the number of outgoing messages that can be held
90
+ # pending confirmation or receipt by the broker.
91
+ #
92
+ # ==== Options
93
+ #
94
+ # * capacity - the capacity
95
+ #
96
+ # ==== Examples
97
+ #
98
+ # sender.capacity = 50 # sets the outgoing capacity to 50 messages
99
+ #
100
+ def capacity=(capacity); @sender_impl.setCapacity capacity; end
101
+
102
+ # Returns the capacity.
103
+ #
104
+ # The capacity is the total number of outgoing messages that can be
105
+ # sent before a called to +send+ begins to block by default.
106
+ #
107
+ # ==== Examples
108
+ #
109
+ # puts "You can send a maximum of #{sender.capacity} messages."
110
+ #
111
+ def capacity; @sender_impl.getCapacity; end
112
+
113
+ # Returns the number of messages sent that are pending receipt
114
+ # confirmation by the broker.
115
+ #
116
+ # ==== Examples
117
+ #
118
+ # if sender.unsettled > 0
119
+ # puts "There are #{sender.unsettled} messages pending."
120
+ # end
121
+ #
122
+ def unsettled; @sender_impl.getUnsettled; end
123
+
124
+ # Returns the available slots for sending messages.
125
+ #
126
+ # This differs from +capacity+ in that it is the available slots in
127
+ # the senders capacity for holding outgoing messages. The difference
128
+ # between capacity and available is the number of messages that
129
+ # have not been delivered yet.
130
+ #
131
+ # ==== Examples
132
+ #
133
+ # puts "You can send #{sender.available} messages before blocking."
134
+ #
135
+ def available
136
+ @sender_impl.getAvailable
137
+ end
138
+
139
+ # Returns the +Session+ for this sender.
140
+ #
141
+ # ==== Examples
142
+ #
143
+ # recv.session.close if done
144
+ #
145
+ def session; @session; end
146
+
147
+ end
148
+
149
+ end
150
+
151
+ end
152
+
@@ -0,0 +1,269 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+
20
+ require 'cqpid'
21
+
22
+ module Qpid
23
+
24
+ module Messaging
25
+
26
+ # A Session represents a distinct conversation between end points.
27
+ class Session
28
+
29
+ def initialize(connection, session) # :nodoc:
30
+ @connection = connection
31
+ @session_impl = session
32
+ @senders = Hash.new
33
+ @receivers = Hash.new
34
+ end
35
+
36
+ def session_impl # :nodoc:
37
+ @session_impl
38
+ end
39
+
40
+ # Returns the +Connection+ associated with this session.
41
+ def connection
42
+ @connection
43
+ end
44
+
45
+ # Creates a new endpoint for sending messages.
46
+ #
47
+ # The +address+ can either be an instance +Address+ or else a
48
+ # string that describes an address endpoint.
49
+ #
50
+ # ==== Arguments
51
+ #
52
+ # * +address+ The end point address.
53
+ #
54
+ # ==== Examples
55
+ #
56
+ # sender = session.create_sender "my-queue;{create:always}"
57
+ #
58
+ def create_sender(address)
59
+ _address = address
60
+
61
+ if address.class == Qpid::Messaging::Address
62
+ _address = address.address_impl
63
+ end
64
+
65
+ sender_impl = @session_impl.createSender(_address)
66
+ sender_name = sender_impl.getName
67
+
68
+ @senders[sender_name] = Qpid::Messaging::Sender.new(self, sender_impl)
69
+
70
+ @senders[sender_name]
71
+ end
72
+
73
+ # Retrieves the +Sender+ with the specified name.
74
+ #
75
+ # The +Sender+ must have been previously created using
76
+ # the +create_sender+ method.
77
+ #
78
+ # ==== Arguments
79
+ #
80
+ # * +name+ The +Sender+ name.
81
+ #
82
+ # ==== Examples
83
+ #
84
+ # sender = session.sender "my-queue"
85
+ #
86
+ def sender(name)
87
+ raise Qpid::Messaging::KeyError, "No such sender: #{name}" unless @senders.has_key? name
88
+
89
+ @senders[name]
90
+ end
91
+
92
+ # Creates a new endpoint for receiving messages.
93
+ #
94
+ # The +address+ can either be an instance +Address+ or else a
95
+ # string that describes an address endpoint.
96
+ #
97
+ # ==== Arguments
98
+ #
99
+ # * +address+ The end point address.
100
+ #
101
+ # ==== Examples
102
+ #
103
+ # receiver = session.create_receiver "my-queue"
104
+ #
105
+ def create_receiver(address)
106
+ result = nil
107
+ receiver_impl = nil
108
+
109
+ if address.class == Qpid::Messaging::Address
110
+ address_impl = address.address_impl
111
+ receiver_impl = @session_impl.createReceiver address_impl
112
+ else
113
+ receiver_impl = @session_impl.createReceiver(address)
114
+ end
115
+
116
+ receiver_name = receiver_impl.getName
117
+
118
+ @receivers[receiver_name] = Qpid::Messaging::Receiver.new self, receiver_impl
119
+
120
+ @receivers[receiver_name]
121
+ end
122
+
123
+ # Retrieves the +Receiver+ with the specified name.
124
+ #
125
+ # The +Receiver+ must have been previously created using
126
+ # the +create_receiver+ method.
127
+ #
128
+ # ==== Arguments
129
+ #
130
+ # * +name+ The +Receiver+ name.
131
+ #
132
+ # ==== Examples
133
+ #
134
+ # receiver = session.receiver "my-queue"
135
+ #
136
+ def receiver(name)
137
+ raise Qpid::Messaging::KeyError, "No such receiver: #{name}" unless @receivers.has_key? name
138
+
139
+ @receivers[name]
140
+ end
141
+
142
+ # Closes the +Session+ and all associated +Sender+ and +Receiver+ instances.
143
+ #
144
+ # NOTE: All +Session+ instances for a +Connection+ are closed when the
145
+ # +Connection+ is closed.
146
+ def close; @session_impl.close; end
147
+
148
+ # Commits any pending transactions for a transactional session.
149
+ def commit; @session_impl.commit; end
150
+
151
+ # Rolls back any uncommitted transactions on a transactional session.
152
+ def rollback; @session_impl.rollback; end
153
+
154
+ # Acknowledges one or more outstanding messages that have been received
155
+ # on this session.
156
+ #
157
+ # ==== Arguments
158
+ #
159
+ # * :message - if specified, then only the +Message+ specified is acknowledged
160
+ # * :sync - if true then the call will block until processed by the server (def. false)
161
+ #
162
+ # ==== Examples
163
+ #
164
+ # session.acknowledge # acknowledges all received messages
165
+ # session.acknowledge :message => message # acknowledge one message
166
+ # session.acknowledge :sync => true # blocks until the call completes
167
+ #
168
+ #--
169
+ # TODO: Add an optional block to be used for blocking calls.
170
+ #++
171
+ def acknowledge(args = {})
172
+ sync = args[:sync] || false
173
+ message = args[:message] if args[:message]
174
+
175
+ unless message.nil?
176
+ @session_impl.acknowledge message.message_impl, sync
177
+ else
178
+ @session_impl.acknowledge sync
179
+ end
180
+ end
181
+
182
+ # Rejects the specified message. A rejected message will not be
183
+ # redelivered.
184
+ #
185
+ # NOTE: A message cannot be rejected once it has been acknowledged.
186
+ def reject(message); @session_impl.reject message.message_impl; end
187
+
188
+ # Releases the message, which allows the broker to attempt to
189
+ # redeliver it.
190
+ #
191
+ # NOTE: A message connot be released once it has been acknowled.
192
+ def release(message); @session_impl.release message.message_impl; end
193
+
194
+ # Requests synchronization with the server.
195
+ #
196
+ # ==== Arguments
197
+ #
198
+ # * :block - if true then the call blocks until the server acknowledges it (def. false)
199
+ #
200
+ #--
201
+ # TODO: Add an optional block to be used for blocking calls.
202
+ #++
203
+ def sync(args = {})
204
+ block = args[:block] || false
205
+ @session_impl.sync block
206
+ end
207
+
208
+ # Returns the total number of receivable messages, and messages already
209
+ # received, by +Receiver+ instances associated with this +Session+.
210
+ def receivable; @session_impl.getReceivable; end
211
+
212
+ # Returns the number of messages that have been acknowledged by this session
213
+ # whose acknowledgements have not been confirmed as processed by the server.
214
+ def unsettled_acks; @session_impl.getUnsettledAcks; end
215
+
216
+ # Fetches the +Receiver+ for the next message.
217
+ #
218
+ # ==== Arguments
219
+ #
220
+ # * timeout - time to wait for a +Receiver+ before timing out
221
+ #
222
+ # ==== Examples
223
+ #
224
+ # recv = session.next_receiver # wait forever for the next +Receiver+
225
+ # # execute a block on the next receiver
226
+ # session.next_receiver do |recv|
227
+ # msg = recv.get
228
+ # puts "Received message: #{msg.content}"
229
+ # end
230
+ def next_receiver(timeout = Qpid::Messaging::Duration::FOREVER, &block)
231
+ receiver_impl = @session_impl.nextReceiver(timeout.duration_impl)
232
+
233
+ unless receiver_impl.nil?
234
+ recv = Qpid::Messaging::Receiver.new self, receiver_impl
235
+ block.call recv unless block.nil?
236
+ end
237
+
238
+ return recv
239
+ end
240
+
241
+ # Returns true if there were exceptions on this session.
242
+ #
243
+ # ==== Examples
244
+ #
245
+ # puts "There were session errors." if @session.errors?
246
+ def errors?; @session_impl.hasError; end
247
+
248
+ # If the +Session+ has been rendered invalid due to some exception,
249
+ # this method will result in that exception being raised.
250
+ #
251
+ # If none have occurred, then no exceptions are raised.
252
+ #
253
+ # ==== Examples
254
+ #
255
+ # if @session.errors?
256
+ # begin
257
+ # @session.errors
258
+ # rescue Exception => error
259
+ # puts "An error occurred: #{error}"
260
+ # end
261
+ # end
262
+ def errors; @session_impl.checkError; end
263
+
264
+ end
265
+
266
+ end
267
+
268
+ end
269
+