rmq 0.0.4 → 0.0.6

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.
data/lib/rmq.rb CHANGED
@@ -8,5 +8,6 @@ require "rmq/message_descriptor"
8
8
  require "rmq/put_message_options"
9
9
  require "rmq/get_message_options"
10
10
  require "rmq/object_descriptor"
11
+ require "rmq/message"
11
12
  require "rmq/queue"
12
13
 
data/lib/rmq/constants.rb CHANGED
@@ -773,6 +773,8 @@ module RMQ
773
773
  completion_codes[completion_code]
774
774
  end
775
775
 
776
+ MQRC_TRUNCATED_MSG_FAILED = 2080
777
+
776
778
  def decode_reason_code(reason_code)
777
779
  reason_codes = {
778
780
  0 => :MQRC_NONE,
@@ -781,7 +783,7 @@ module RMQ
781
783
  2033 => :MQRC_NO_MSG_AVAILABLE,
782
784
  2037 => :MQRC_NOT_OPEN_FOR_INPUT,
783
785
  2079 => :MQRC_TRUNCATED_MSG_ACCEPTED,
784
- 2080 => :MQRC_TRUNCATED_MSG_FAILED,
786
+ MQRC_TRUNCATED_MSG_FAILED => :MQRC_TRUNCATED_MSG_FAILED,
785
787
  2186 => :MQRC_GMO_ERROR,
786
788
  2309 => :MQRC_SELECTOR_NOT_PRESENT,
787
789
  2320 => :MQRC_HBAG_ERROR,
@@ -14,4 +14,8 @@ module RMQ
14
14
  "#{to_s}. Reason code = #{decode_reason_code(reason_code)} (#{reason_code}), completion code = #{decode_completion_code(completion_code)}"
15
15
  end
16
16
  end
17
+
18
+ class RMQTimeOutError < RuntimeError
19
+ end
20
+
17
21
  end
@@ -0,0 +1,14 @@
1
+ module RMQ
2
+ class Message
3
+ attr_reader :payload
4
+
5
+ def initialize(payload, message_descriptor)
6
+ @payload = payload
7
+ @message_descriptor = message_descriptor
8
+ end
9
+
10
+ def reply_queue_name
11
+ @message_descriptor[:ReplyToQ].to_s.strip
12
+ end
13
+ end
14
+ end
@@ -9,6 +9,8 @@ module RMQ
9
9
  MQMT_DATAGRAM = 8
10
10
  MQPER_PERSISTENT = 1
11
11
 
12
+ MSG_ID_LENGTH = 24
13
+
12
14
  layout :StrucId, [:char, 4],
13
15
  :Version, :long,
14
16
  :Report, :long,
@@ -20,7 +22,7 @@ module RMQ
20
22
  :Format, [:char, 8],
21
23
  :Priority, :long,
22
24
  :Persistence, :long,
23
- :MsgId, [:char, 24],
25
+ :MsgId, [:char, MSG_ID_LENGTH],
24
26
  :CorrelId, [:char, 24],
25
27
  :BackoutCount, :long,
26
28
  :ReplyToQ, [:char, 48],
data/lib/rmq/mqclient.rb CHANGED
@@ -251,31 +251,73 @@ module RMQ
251
251
  queue_depth
252
252
  end
253
253
 
254
- def get_message_from_queue(connection_handle, queue_handle)
254
+ def get_message_from_queue(connection_handle, queue_handle, timeout)
255
+ puts "--- get message from queue"
255
256
  completion_code_ptr = FFI::MemoryPointer.new :long
256
257
  reason_code_ptr = FFI::MemoryPointer.new :long
257
258
  data_length_ptr = FFI::MemoryPointer.new :long
258
259
 
260
+ message_options = prepare_get_message_options(timeout, false)
261
+ message_descriptor = prepare_get_message_descriptor
262
+
263
+ data_length = 8 * 1024
264
+ buffer_ptr = FFI::MemoryPointer.new :char, data_length
265
+
266
+ mqget(connection_handle, queue_handle, message_descriptor, message_options, data_length, buffer_ptr, data_length_ptr, completion_code_ptr, reason_code_ptr)
267
+
268
+ if (completion_code_ptr.read_long == MQCC_WARNING && reason_code_ptr.read_long == MQRC_TRUNCATED_MSG_FAILED)
269
+ msg_id = message_descriptor[:MsgId]
270
+ data_length = data_length_ptr.read_long
271
+ buffer_ptr = FFI::MemoryPointer.new :char, data_length
272
+ message_descriptor = prepare_get_message_descriptor(msg_id)
273
+ mqget(connection_handle, queue_handle, message_descriptor, message_options, data_length, buffer_ptr, data_length_ptr, completion_code_ptr, reason_code_ptr)
274
+ raise RMQException.new(completion_code_ptr.read_long, reason_code_ptr.read_long), "Cannot read message again after learning message length" if completion_code_ptr.read_long == MQCC_FAILED
275
+ else
276
+ raise RMQException.new(completion_code_ptr.read_long, reason_code_ptr.read_long), "Cannot learn message length" unless completion_code_ptr.read_long == MQCC_OK
277
+ end
278
+
279
+ Message.new(buffer_ptr.read_string, message_descriptor)
280
+ end
281
+
282
+ private
283
+
284
+ def prepare_get_message_options(timeout, accept_truncated_msg)
259
285
  message_options = GetMessageOptions.new
260
286
  message_options[:StrucId] = GetMessageOptions::MQGMO_STRUC_ID
261
287
  message_options[:Version] = GetMessageOptions::MQGMO_VERSION_1
262
- message_options[:Options] = GetMessageOptions::MQGMO_ACCEPT_TRUNCATED_MSG
288
+ message_options[:Options] = 0
289
+
290
+ if accept_truncated_msg
291
+ message_options[:Options] = GetMessageOptions::MQGMO_ACCEPT_TRUNCATED_MSG | message_options[:Options]
292
+ end
263
293
 
294
+ if timeout > 0
295
+ message_options[:Options] = GetMessageOptions::MQGMO_WAIT | message_options[:Options]
296
+ message_options[:WaitInterval] = timeout * 1000
297
+ end
298
+
299
+ message_options
300
+ end
301
+
302
+ def print_msg_id(msg_id)
303
+ puts "printing msg id"
304
+ for i in (0..MQClient::MessageDescriptor::MSG_ID_LENGTH-1) do
305
+ puts "#{i} = #{msg_id[i]}"
306
+ end
307
+ end
308
+
309
+ def prepare_get_message_descriptor(msg_id = nil)
264
310
  message_descriptor = MQClient::MessageDescriptor.new
265
311
  message_descriptor[:StrucId] = MQClient::MessageDescriptor::MQMD_STRUC_ID
266
312
  message_descriptor[:Version] = MQClient::MessageDescriptor::MQMD_VERSION_1
267
313
 
268
- # TODO determine message length and then reissue call
269
- # mqget(connection_handle, queue_handle, message_descriptor, message_options, 0, nil, data_length_ptr, completion_code_ptr, reason_code_ptr)
270
- # raise RMQException.new(completion_code_ptr.read_long, reason_code_ptr.read_long), "Cannot learn message length" if completion_code_ptr.read_long == MQCC_FAILED
271
-
272
- # data_length = data_length_ptr.read_long
273
- data_length = 8192
274
- buffer_ptr = FFI::MemoryPointer.new :char, data_length
275
- mqget(connection_handle, queue_handle, message_descriptor, message_options, data_length, buffer_ptr, data_length_ptr, completion_code_ptr, reason_code_ptr)
276
- raise RMQException.new(completion_code_ptr.read_long, reason_code_ptr.read_long), "Cannot learn message length" if completion_code_ptr.read_long == MQCC_FAILED
314
+ if !msg_id.nil?
315
+ for i in (0..MQClient::MessageDescriptor::MSG_ID_LENGTH-1) do
316
+ message_descriptor[:MsgId][i] = msg_id[i]
317
+ end
318
+ end
277
319
 
278
- buffer_ptr.read_string
320
+ message_descriptor
279
321
  end
280
322
 
281
323
  end
data/lib/rmq/queue.rb CHANGED
@@ -9,6 +9,7 @@ module RMQ
9
9
  @queue_name = name
10
10
  end
11
11
 
12
+ # Puts a message onto the queue. A reply to queue name can be specified.
12
13
  def put_message(payload, reply_queue_name = "")
13
14
  @queue_handle = open_queue(@queue_manager.connection_handle, @queue_name, Constants::MQOO_OUTPUT) if @queue_handle.nil?
14
15
 
@@ -22,15 +23,33 @@ module RMQ
22
23
  queue_depth(@queue_manager.connection_handle, @queue_name)
23
24
  end
24
25
 
25
- def get_message
26
+ # Gets a message from the queue. A timeout period can be specified in seconds.
27
+ def get_message(timeout = 0)
26
28
  @queue_handle = open_queue(@queue_manager.connection_handle, @queue_name, Constants::MQOO_INPUT_SHARED) if @queue_handle.nil?
27
29
 
28
- payload = get_message_from_queue(@queue_manager.connection_handle, @queue_handle)
30
+ if (timeout > 0)
31
+ begin_time = Time.now.to_i
32
+ begin
33
+ message = get_message_from_queue(@queue_manager.connection_handle, @queue_handle, timeout)
34
+ rescue RMQException
35
+ end_time = Time.now.to_i
36
+ raise RMQTimeOutError.new if end_time - begin_time >= timeout
37
+ end
38
+ else
39
+ message = get_message_from_queue(@queue_manager.connection_handle, @queue_handle, 0)
40
+ end
29
41
 
30
42
  close_queue(@queue_manager.connection_handle, @queue_handle, Constants::MQCO_NONE)
31
43
  @queue_handle = nil
32
44
 
33
- payload
45
+ message
46
+ end
47
+
48
+ # Gets a message from the queue and returns the payload only. A timeout period can be specified
49
+ # in seconds.
50
+ def get_message_payload(timeout = 0)
51
+ message = get_message(timeout)
52
+ message.payload
34
53
  end
35
54
  end
36
55
  end
data/lib/rmq/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RMQ
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -1,8 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe RMQ::QueueManager do
4
+ SAMPLE_QUEUE = SpecHelper::DATA[:sample_queue]
4
5
 
5
6
  after(:each) do
7
+ begin
8
+ @qm.delete_queue(SAMPLE_QUEUE) if !@qm.find_queue(SAMPLE_QUEUE).nil?
9
+ rescue
10
+ puts "Cannot delete #{SAMPLE_QUEUE}"
11
+ end
6
12
  @qm.disconnect if !@qm.nil?
7
13
  end
8
14
 
@@ -27,17 +33,17 @@ describe RMQ::QueueManager do
27
33
 
28
34
  it "should create a new queue" do
29
35
  @qm = RMQ::QueueManager::connect(SpecHelper::DATA[:queue_manager])
30
- queue = @qm.create_queue("RMQ.SAMPLE")
36
+ queue = @qm.create_queue(SAMPLE_QUEUE)
31
37
  queue.should_not be_nil
32
38
 
33
- @qm.find_queue("RMQ.SAMPLE").should_not be_nil
39
+ @qm.find_queue(SAMPLE_QUEUE).should_not be_nil
34
40
 
35
- @qm.delete_queue("RMQ.SAMPLE")
41
+ @qm.delete_queue(SAMPLE_QUEUE)
36
42
  end
37
43
 
38
44
  it "should find an existing queue" do
39
45
  @qm = RMQ::QueueManager::connect(SpecHelper::DATA[:queue_manager])
40
- @qm.find_queue("SYSTEM.ADMIN.COMMAND.QUEUE").should_not be_nil # SAMPLE_IN needs to be changed to one that always exists
46
+ @qm.find_queue("SYSTEM.ADMIN.COMMAND.QUEUE").should_not be_nil
41
47
  end
42
48
 
43
49
  it "should not find a non-existing queue" do
@@ -47,11 +53,11 @@ describe RMQ::QueueManager do
47
53
 
48
54
  it "should delete a queue" do
49
55
  @qm = RMQ::QueueManager::connect(SpecHelper::DATA[:queue_manager])
50
- @qm.create_queue("RMQ.SAMPLE")
51
- @qm.find_queue("RMQ.SAMPLE").should_not be_nil
56
+ @qm.create_queue(SAMPLE_QUEUE)
57
+ @qm.find_queue(SAMPLE_QUEUE).should_not be_nil
52
58
 
53
- @qm.delete_queue("RMQ.SAMPLE")
54
- @qm.find_queue("RMQ.SAMPLE").should be_nil
59
+ @qm.delete_queue(SAMPLE_QUEUE)
60
+ @qm.find_queue(SAMPLE_QUEUE).should be_nil
55
61
  end
56
62
 
57
63
  end
@@ -1,16 +1,21 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe RMQ::Queue do
4
+ SAMPLE_QUEUE = SpecHelper::DATA[:sample_queue]
4
5
 
5
6
  before(:each) do
6
7
  @qm = RMQ::QueueManager::connect(SpecHelper::DATA[:queue_manager])
7
8
 
8
- @qm.delete_queue("RMQ.SAMPLE") unless @qm.find_queue("RMQ.SAMPLE").nil?
9
- @queue = @qm.create_queue("RMQ.SAMPLE")
9
+ @qm.delete_queue(SAMPLE_QUEUE) unless @qm.find_queue(SAMPLE_QUEUE).nil?
10
+ @queue = @qm.create_queue(SAMPLE_QUEUE)
10
11
  end
11
12
 
12
13
  after(:each) do
13
- @qm.delete_queue("RMQ.SAMPLE")
14
+ begin
15
+ @qm.delete_queue(SAMPLE_QUEUE)
16
+ rescue
17
+ puts "Cannot delete #{SAMPLE_QUEUE}"
18
+ end
14
19
  @qm.disconnect if !@qm.nil?
15
20
  end
16
21
 
@@ -21,11 +26,22 @@ describe RMQ::Queue do
21
26
 
22
27
  it "should read a message from a queue" do
23
28
  @queue.put_message("I want to read this back")
24
- @queue.get_message.should == "I want to read this back"
29
+ @queue.get_message_payload.should == "I want to read this back"
25
30
  end
26
31
 
27
32
  it "should put a message on a queue and use a reply queue name" do
33
+ @queue.put_message("I want to read this back", "REPLY_QUEUE")
34
+ message = @queue.get_message
35
+ message.should_not be_nil
36
+ message.reply_queue_name.should == "REPLY_QUEUE"
37
+ end
38
+
39
+ it "should time out waiting for a message" do
40
+ lambda { @queue.get_message(2) }.should raise_error(RMQ::RMQTimeOutError)
41
+ end
28
42
 
43
+ it "should time out waiting for a message and not return any payload" do
44
+ lambda { @queue.get_message_payload(2) }.should raise_error(RMQ::RMQTimeOutError)
29
45
  end
30
46
 
31
47
  end
data/spec/spec_helper.rb CHANGED
@@ -5,7 +5,8 @@ MQSERVER = "SYSTEM.DEF.SVRCONN/TCP/127.0.0.1(1414)"
5
5
 
6
6
  module SpecHelper
7
7
  DATA = {
8
- :queue_manager => "BKR_QMGR"
8
+ :queue_manager => "BKR_QMGR",
9
+ :sample_queue => "RMQ.SAMPLE"
9
10
  }
10
11
  end
11
12
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rmq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-02-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &21388056 !ruby/object:Gem::Requirement
16
+ requirement: &22131996 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '2.7'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *21388056
24
+ version_requirements: *22131996
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: ffi
27
- requirement: &21387768 !ruby/object:Gem::Requirement
27
+ requirement: &22131528 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *21387768
35
+ version_requirements: *22131528
36
36
  description: Ruby wrapper around MQ series client library
37
37
  email: sns@caimito.net
38
38
  executables: []
@@ -42,6 +42,7 @@ files:
42
42
  - lib/rmq/constants.rb
43
43
  - lib/rmq/exceptions.rb
44
44
  - lib/rmq/get_message_options.rb
45
+ - lib/rmq/message.rb
45
46
  - lib/rmq/message_descriptor.rb
46
47
  - lib/rmq/mqclient.rb
47
48
  - lib/rmq/object_descriptor.rb