jerryluk-rabbitmq-jruby-client 0.1.4 → 0.1.5

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