jerryluk-rabbitmq-jruby-client 0.1.4 → 0.1.5

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/README CHANGED
@@ -1,22 +1,49 @@
1
-
2
- This project is a JRuby wrapper of the Java RabbitMQ Client from Rabbit Technologies
3
-
4
- http://www.rabbitmq.com/
5
-
6
- Using this library does not require you to use EventMachine for subscribing a RabbitMQ queue.
7
-
8
- To use RabbitMQ JRuby Client with Workling:
9
- 1. Copy workling_rabbitmq_client.rb and workling_rabbitmq_subscriber.rb to lib
10
- Create an initializer 'rabbitmq.rb' in 'config/initializers'
11
-
12
- require 'workling_rabbitmq_client'
13
- Workling::Remote.dispatcher = Workling::Remote::Runners::ClientRunner.new
14
- Workling::Remote.dispatcher.client = Workling::Clients::WorklingRabbitMQClient.new
15
-
16
- Optional: To use subscriber
17
- Modify vendor/plugins/workling/script/listen.rb, added this after the require statements
18
-
19
- require 'workling_rabbitmq_subscriber'
20
-
21
- To start Workling: (You can use script/workling_client because it uses daemons)
22
- jruby vendor/plugins/workling/script/listen.rb
1
+ RabbitMQ JRuby Client
2
+ =====================
3
+ rabbitmq-jruby-client allows you to use RabbitMQ Client from JRuby using the official Java RabbitMQ client from Rabbit Technologies
4
+ See more at http://www.rabbitmq.com
5
+
6
+ Getting Started
7
+ ===============
8
+ 1. Make sure you can install RubyGem from GitHub (you only have to do this once): jruby -S gem sources -a http://gems.github.com
9
+ 2. Install and start RabbitMQ (see below)
10
+ 3. Install JRuby RabbitMQ Client: jruby -S gem install jerryluk-rabbitmq-jruby-client
11
+
12
+ Example Usage
13
+ =============
14
+ gem 'jerryluk-rabbitmq-jruby-client'
15
+ require 'rabbitmq_client'
16
+
17
+ # Initializes the new client and connect to the server
18
+ client = RabbitMQClient.new
19
+
20
+ # Initializes a new queue
21
+ queue = client.queue('queue_name')
22
+
23
+ # Initializes a new exchange
24
+ exchange = client.exchange('exchange_name')
25
+
26
+ # Connects queue with the exchange
27
+ queue.bind(exchange)
28
+
29
+ # Publish a message to the queue
30
+ queue.publish('message body')
31
+
32
+ # Retrieve a message from the queue
33
+ message = queue.retrieve
34
+
35
+ # Subscribe to a queue with callback
36
+ queue.subscribe do |message|
37
+ # do something with message
38
+ end
39
+
40
+ Installing RabbitMQ on OS X
41
+ ===========================
42
+ 1. Install MacPorts
43
+ 2. sudo port install erlang
44
+ 3. wget http://www.rabbitmq.com/releases/rabbitmq-server/v1.5.3/rabbitmq-server-generic-unix-1.5.3.tar.gz
45
+ 4. tar zxvf rabbitmq-server-1.5.3.tar.gz
46
+ 5. sudo mv rabbitmq_server-1.5.3 /opt/local/lib/erlang/lib
47
+
48
+ To run RabbitMQ
49
+ 6. sudo /opt/local/lib/erlang/lib/rabbitmq_server-1.5.3/sbin/rabbitmq-server
@@ -12,8 +12,11 @@ class RabbitMQClient
12
12
  include_class('com.rabbitmq.client.Channel')
13
13
  include_class('com.rabbitmq.client.Consumer')
14
14
  include_class('com.rabbitmq.client.DefaultConsumer')
15
+ include_class('com.rabbitmq.client.MessageProperties')
15
16
  include_class('java.lang.String') { |package, name| "J#{name}" }
16
17
 
18
+ class RabbitMQClientError < StandardError;end
19
+
17
20
  class QueueConsumer < DefaultConsumer
18
21
  def initialize(channel, block)
19
22
  @channel = channel
@@ -24,26 +27,36 @@ class RabbitMQClient
24
27
  def handleDelivery(consumer_tag, envelope, properties, body)
25
28
  delivery_tag = envelope.get_delivery_tag
26
29
  message_body = Marshal.load(String.from_java_bytes(body))
30
+ # TODO: Do we need to do something with properties?
27
31
  @block.call message_body
28
32
  @channel.basic_ack(delivery_tag, false)
29
33
  end
30
34
  end
31
35
 
32
36
  class Queue
33
- def initialize(name, channel)
37
+ def initialize(name, channel, durable=false)
34
38
  @name = name
39
+ @durable = durable
35
40
  @channel = channel
36
- @channel.queue_declare(name)
41
+ @channel.queue_declare(name, durable)
37
42
  self
38
43
  end
39
44
 
40
- def bind(exchange, routing_key=nil)
41
- @routing_key = routing_key || "#{@name}_#{Time.now.to_i.to_s}_#{rand(1<<64).to_s}"
45
+ def bind(exchange, routing_key='')
46
+ @routing_key = routing_key
42
47
  @exchange = exchange
48
+ raise RabbitMQClientError, "queue and exchange has different durable property" unless @durable == exchange.durable
43
49
  @channel.queue_bind(@name, @exchange.name, @routing_key)
44
50
  self
45
51
  end
46
52
 
53
+ # Set props for different type of message. Currently they are:
54
+ # RabbitMQClient::MessageProperties::MINIMAL_BASIC
55
+ # RabbitMQClient::MessageProperties::MINIMAL_PERSISTENT_BASIC
56
+ # RabbitMQClient::MessageProperties::BASIC
57
+ # RabbitMQClient::MessageProperties::PERSISTENT_BASIC
58
+ # RabbitMQClient::MessageProperties::TEXT_PLAIN
59
+ # RabbitMQClient::MessageProperties::PERSISTENT_TEXT_PLAIN
47
60
  def publish(message_body, props=nil)
48
61
  auto_bind
49
62
  message_body_byte = Marshal.dump(message_body).to_java_bytes
@@ -51,6 +64,11 @@ class RabbitMQClient
51
64
  message_body
52
65
  end
53
66
 
67
+ def persistent_publish(message_body, props=MessageProperties::PERSISTENT_BASIC)
68
+ raise RabbitMQClientError, "can only publish persistent message to durable queue" unless @durable
69
+ publish(message_body, props)
70
+ end
71
+
54
72
  def retrieve
55
73
  auto_bind
56
74
  message_body = nil
@@ -73,7 +91,7 @@ class RabbitMQClient
73
91
  protected
74
92
  def auto_bind
75
93
  unless @exchange
76
- exchange = Exchange.new("#{@name}_exchange", 'fanout', @channel)
94
+ exchange = Exchange.new("#{@name}_exchange", 'fanout', @channel, @durable)
77
95
  self.bind(exchange)
78
96
  end
79
97
  end
@@ -81,12 +99,14 @@ class RabbitMQClient
81
99
 
82
100
  class Exchange
83
101
  attr_reader :name
102
+ attr_reader :durable
84
103
 
85
- def initialize(name, type, channel)
104
+ def initialize(name, type, channel, durable=false)
86
105
  @name = name
87
106
  @type = type
107
+ @durable = durable
88
108
  @channel = channel
89
- @channel.exchange_declare(@name, type.to_s)
109
+ @channel.exchange_declare(@name, type.to_s, durable)
90
110
  self
91
111
  end
92
112
  end
@@ -99,7 +119,7 @@ class RabbitMQClient
99
119
  attr_reader :connection
100
120
 
101
121
  # Instance Methods
102
- def initialize(options={})
122
+ def initialize(options={:auto_connect => true})
103
123
  # server address
104
124
  @host = options[:host] || '127.0.0.1'
105
125
  @port = options[:port] || 5672
@@ -113,7 +133,7 @@ class RabbitMQClient
113
133
  @queues = {}
114
134
  @exchanges = {}
115
135
 
116
- connect
136
+ connect if options[:auto_connect]
117
137
  # Disconnect before the object is destroyed
118
138
  define_finalizer(self, lambda {|id| self.disconnect if self.connected? })
119
139
  self
@@ -140,12 +160,12 @@ class RabbitMQClient
140
160
  @connection != nil
141
161
  end
142
162
 
143
- def queue(name)
144
- @queues[name] ||= Queue.new(name, @channel)
163
+ def queue(name, durable=false)
164
+ @queues[name] ||= Queue.new(name, @channel, durable)
145
165
  end
146
166
 
147
- def exchange(name, type='fanout')
148
- @exchanges[name] ||= Exchange.new(name, type, @channel)
167
+ def exchange(name, type='fanout', durable=false)
168
+ @exchanges[name] ||= Exchange.new(name, type, @channel, durable)
149
169
  end
150
170
  end
151
171
 
@@ -7,6 +7,10 @@ describe RabbitMQClient do
7
7
  @client = RabbitMQClient.new
8
8
  end
9
9
 
10
+ after(:each) do
11
+ @client.disconnect
12
+ end
13
+
10
14
  it "should able to create a connection" do
11
15
  @client.connection.should_not be_nil
12
16
  end
@@ -20,7 +24,7 @@ describe RabbitMQClient do
20
24
  exchange.should_not be_nil
21
25
  end
22
26
 
23
- describe Queue do
27
+ describe Queue, "Basic non-persistent queue" do
24
28
  before(:each) do
25
29
  @queue = @client.queue('test_queue')
26
30
  @exchange = @client.exchange('test_exchange', 'direct')
@@ -51,5 +55,50 @@ describe RabbitMQClient do
51
55
  sleep 1
52
56
  a.should == 3
53
57
  end
58
+
59
+ it "should raise an exception if binding a persistent queue with non-persistent exchange and vice versa" do
60
+ persistent_queue = @client.queue('test_queue1', true)
61
+ persistent_exchange = @client.exchange('test_exchange1', 'fanout', true)
62
+ lambda { persistent_queue.bind(@exchange) }.should raise_error(RabbitMQClient::RabbitMQClientError)
63
+ lambda { @queue.bind(persistent_exchange) }.should raise_error(RabbitMQClient::RabbitMQClientError)
64
+ end
65
+
66
+ it "should raise an exception if publish a persistent message on non-duration queue" do
67
+ @queue.bind(@exchange)
68
+ lambda { @queue.persistent_publish('Hello') }.should raise_error(RabbitMQClient::RabbitMQClientError)
69
+ end
70
+ end
71
+
72
+ describe Queue, "Basic persistent queue" do
73
+ before(:each) do
74
+ @queue = @client.queue('test_durable_queue', true)
75
+ @exchange = @client.exchange('test_durable_exchange', 'fanout', true)
76
+ end
77
+
78
+ it "should able to create a queue" do
79
+ @queue.should_not be_nil
80
+ end
81
+
82
+ it "should able to bind to an exchange" do
83
+ @queue.bind(@exchange).should_not be_nil
84
+ end
85
+
86
+ it "should able to publish and retrieve a message" do
87
+ @queue.bind(@exchange)
88
+ @queue.persistent_publish('Hello World')
89
+ @queue.retrieve.should == 'Hello World'
90
+ end
91
+
92
+ it "should able to subscribe with a callback function" do
93
+ a = 0
94
+ @queue.bind(@exchange)
95
+ @queue.subscribe do |v|
96
+ a += v.to_i
97
+ end
98
+ @queue.persistent_publish("1")
99
+ @queue.persistent_publish("2")
100
+ sleep 1
101
+ a.should == 3
102
+ end
54
103
  end
55
104
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jerryluk-rabbitmq-jruby-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry Luk