qpid_messaging 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
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
+