jack_rabbit 0.1.0-java → 0.2.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,15 +2,23 @@ $:.push(File.expand_path('../../lib', __FILE__))
2
2
 
3
3
  require 'uri'
4
4
  require 'jack_rabbit'
5
+ require 'logger'
6
+ require 'thread'
7
+
8
+ $stdout.sync = true
9
+
10
+ Thread.abort_on_exception = true
5
11
 
6
12
  subscriptions = [
7
13
  # exchange key queue
8
14
  [ 'jackrabbitdev', 'consumer.test', 'consumer.test', {} ]
9
15
  ]
10
16
 
11
- consumer = JackRabbit::Consumer.new
17
+ consumer = JackRabbit::Consumer.new(Logger.new($stdout))
12
18
 
13
- consumer.connect([ URI.parse('amqp://guest:guest@localhost:5672/') ])
19
+ consumer.connect([
20
+ URI.parse('amqp://guest:guest@localhost:5672/')
21
+ ])
14
22
 
15
23
  subscriptions.each do |exchange, key, queue, options|
16
24
  consumer.subscribe(exchange, key, queue, options) do |header, message|
@@ -2,12 +2,21 @@ $:.push(File.expand_path('../../lib', __FILE__))
2
2
 
3
3
  require 'uri'
4
4
  require 'jack_rabbit'
5
+ require 'logger'
6
+ require 'thread'
5
7
 
6
- producer = JackRabbit::Producer.new
8
+ $stdout.sync = true
9
+
10
+ Thread.abort_on_exception = true
11
+
12
+ producer = JackRabbit::Producer.new(Logger.new($stdout))
7
13
 
8
14
  producer.connect(URI.parse('amqp://guest:guest@localhost:5672/'))
9
15
 
16
+ n = 0
10
17
  loop do
11
- puts producer.publish('jackrabbitdev', :direct, 'consumer.test', 'foo')
18
+ message = (n += 1).to_s
19
+ producer.publish('jackrabbitdev', :direct, 'consumer.test', message)
20
+ puts(message)
12
21
  sleep(1)
13
22
  end
@@ -0,0 +1,15 @@
1
+ module JackRabbit
2
+ module Backoff
3
+ MAX = 16 # seconds
4
+
5
+ def with_backoff(exception, f = ->(n) { n < MAX ? 2**n : MAX }, &block)
6
+ n = 0
7
+ begin
8
+ yield
9
+ rescue exception
10
+ sleep(n = f[n])
11
+ retry
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ require 'jack_rabbit/subscription'
2
+ require 'jack_rabbit/logging'
3
+
4
+ module JackRabbit
5
+ class Channel
6
+ include Logging
7
+
8
+ EXCHANGE_OPTIONS = { durable: true, type: :direct }
9
+
10
+ QUEUE_OPTIONS = { durable: true }
11
+
12
+ def initialize(connection, options)
13
+ @connection, @options = connection, options
14
+ @subscriptions = []
15
+ end
16
+
17
+ def open
18
+ open_channel(@connection, @options)
19
+ self
20
+ end
21
+
22
+ def close
23
+ @channel.close
24
+ end
25
+
26
+ def subscribe(exchange, key, queue, options, &block)
27
+ sub = Subscription.new(self, exchange, key, queue, options, &block)
28
+ @subscriptions << sub
29
+ sub.declare
30
+ sub
31
+ end
32
+
33
+ def reopen
34
+ open_channel(@connection, @options)
35
+ @subscriptions.each { |sub| sub.declare }
36
+ end
37
+
38
+ def create_exchange(name, options)
39
+ @channel.exchange(name, EXCHANGE_OPTIONS.merge(options))
40
+ end
41
+
42
+ def create_queue(name, options)
43
+ @channel.queue(name, QUEUE_OPTIONS.merge(options))
44
+ end
45
+
46
+ private
47
+
48
+ def open_channel(connection, options)
49
+ debug('opening channel...')
50
+ channel = connection.create_channel
51
+ channel.prefetch(options[:prefetch]) if options[:prefetch]
52
+ channel.add_shutdown_listener { |_reason| connection.reconnect }
53
+ @channel = channel
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,20 @@
1
+ require 'jack_rabbit/connection'
2
+
3
+ module JackRabbit
4
+ module Client
5
+ private
6
+
7
+ def open_connection(uri, options)
8
+ Connection.new(uri, options)
9
+ .set_logger(@logger)
10
+ .open
11
+ end
12
+
13
+ def open_channel(connection, options)
14
+ connection
15
+ .channel(options)
16
+ .set_logger(@logger)
17
+ .open
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,65 @@
1
+ require 'hot_bunnies'
2
+ require 'jack_rabbit/backoff'
3
+ require 'jack_rabbit/channel'
4
+ require 'jack_rabbit/logging'
5
+
6
+ module JackRabbit
7
+ class Connection
8
+ include Backoff
9
+ include Logging
10
+
11
+ DEFAULT_OPTIONS = { connection_timeout: 5, heartbeat_interval: 5 }
12
+
13
+ def initialize(uri, options)
14
+ @uri, @options = uri, options.merge(connection_options(uri))
15
+ @channels = []
16
+ end
17
+
18
+ def open
19
+ open_connection(@uri, @options)
20
+ self
21
+ end
22
+
23
+ def close
24
+ @connection.close
25
+ end
26
+
27
+ def channel(options)
28
+ channel = Channel.new(self, options)
29
+ @channels << channel
30
+ channel
31
+ end
32
+
33
+ def reopen(reason)
34
+ debug('%s, reconnecting...' % reason.inspect)
35
+ open_connection(@uri, @options)
36
+ @channels.each { |channel| channel.reopen }
37
+ end
38
+
39
+ def create_channel
40
+ @connection.create_channel
41
+ end
42
+
43
+ private
44
+
45
+ def open_connection(uri, options)
46
+ connection =
47
+ with_backoff(Java::JavaNet::ConnectException) do
48
+ info('connecting to %s:%d...' % [ uri.host, uri.port ])
49
+ HotBunnies.connect(options)
50
+ end
51
+ connection.add_shutdown_listener { |reason| reopen(reason) }
52
+ @connection = connection
53
+ end
54
+
55
+ def connection_options(uri)
56
+ DEFAULT_OPTIONS.merge({
57
+ host: uri.host,
58
+ pass: uri.password,
59
+ port: uri.port,
60
+ user: uri.user,
61
+ vhost: uri.path
62
+ })
63
+ end
64
+ end
65
+ end
@@ -1,79 +1,35 @@
1
- require 'hot_bunnies'
2
- require 'jack_rabbit/message_header'
1
+ require 'jack_rabbit/client'
3
2
 
4
3
  module JackRabbit
5
4
  class Consumer
6
- EXCHANGE_OPTIONS = { durable: true, type: :direct }
7
- QUEUE_OPTIONS = { durable: true }
8
- SUBSCRIBE_OPTIONS = { blocking: false }
5
+ include Client
9
6
 
10
- def initialize
11
- @connections = []
12
- @channels = []
13
- @subscriptions = []
7
+ def initialize(logger = nil)
8
+ @logger = logger
14
9
  end
15
10
 
16
11
  def connect(uris, options = {})
17
- uris.inject(@connections) do |memo, uri|
18
- memo.push(open_connection(uri, options))
19
- end
12
+ @connections = uris.map { |uri| open_connection(uri, options) }
20
13
  end
21
14
 
22
15
  def subscribe(exchange, key, queue, options = {}, &block)
23
- channels = open_channels(options[:prefetch])
24
- bind_queues(channels, exchange, key, queue, options) do |meta, message|
25
- block.call(MessageHeader.new(meta), message)
16
+ @connections.each do |connection|
17
+ channel = open_channel(connection, options)
18
+ declare_subscription(channel, exchange, key, queue, options, &block)
26
19
  end
27
20
  end
28
21
 
29
22
  def disconnect
30
- @subscriptions.each(&:shutdown!)
31
- (@channels + @connections).each(&:close)
23
+ @connections.each { |connection| connection.close }
32
24
  end
33
25
 
34
26
  private
35
27
 
36
- def open_connection(uri, options)
37
- connection =
38
- HotBunnies.connect(options.merge(
39
- host: uri.host,
40
- pass: uri.password,
41
- port: uri.port,
42
- user: uri.user,
43
- vhost: uri.path
44
- ))
45
- connection.add_shutdown_listener { |_reason| exit! }
46
- connection
47
- end
48
-
49
- def open_channels(prefetch)
50
- @connections.inject(@channels) do |memo, connection|
51
- channel = connection.create_channel
52
- channel.add_shutdown_listener { |_reason| exit! }
53
- channel.prefetch = prefetch if prefetch
54
- memo.push(channel)
55
- end
56
- end
57
-
58
- def bind_queues(channels, exchange_name, key, queue_name, options, &block)
59
- channels.inject(@subscriptions) do |memo, channel|
60
- exchange = declare_exchange(channel, exchange_name, options)
61
- queue =
62
- bind_queue(channel, exchange, queue_name, key, options).tap do |q|
63
- q.subscribe(SUBSCRIBE_OPTIONS.merge(options), &block)
64
- end
65
- memo.push(queue)
66
- end
67
- end
68
-
69
- def bind_queue(channel, exchange, name, key, options)
28
+ def declare_subscription(channel, exchange, key, queue, options, &block)
70
29
  channel
71
- .queue(name, QUEUE_OPTIONS.merge(Hash(options[:queue])))
72
- .tap { |q| q.bind(exchange, { routing_key: key }) }
73
- end
74
-
75
- def declare_exchange(channel, name, options)
76
- channel.exchange(name, EXCHANGE_OPTIONS.merge(Hash(options[:exchange])))
30
+ .subscribe(exchange, key, queue, options, &block)
31
+ .set_logger(@logger)
77
32
  end
78
33
  end
79
34
  end
35
+
@@ -0,0 +1,24 @@
1
+ module JackRabbit
2
+ module Logging
3
+ TAG = '[jack_rabbit] '
4
+
5
+ def set_logger(logger)
6
+ @logger = logger
7
+ self
8
+ end
9
+
10
+ private
11
+
12
+ def debug(message)
13
+ log(:debug, message)
14
+ end
15
+
16
+ def info(message)
17
+ log(:info, message)
18
+ end
19
+
20
+ def log(severity, message)
21
+ @logger.send(severity, TAG + message) if @logger
22
+ end
23
+ end
24
+ end
@@ -1,50 +1,33 @@
1
- require 'hot_bunnies'
1
+ require 'jack_rabbit/backoff'
2
+ require 'jack_rabbit/client'
2
3
 
3
4
  module JackRabbit
4
5
  class Producer
5
- EXCHANGE_OPTIONS = { auto_delete: false, durable: true }
6
+ include Backoff
7
+ include Client
8
+ include Logging
6
9
 
7
- def connect(uri, options = {})
8
- @channel = (@connection = open_connection(uri, options)).create_channel
10
+ def initialize(logger = nil)
11
+ @logger = logger
9
12
  end
10
13
 
11
- def disconnect
12
- [ @channel, @connection ].each(&:close)
14
+ def connect(uri, options = {})
15
+ @connection = open_connection(uri, options)
16
+ @channel = open_channel(@connection, options)
13
17
  end
14
18
 
15
- def publish(exchange_name, exchange_type, routing_key, message, headers = {})
16
- with_exchange(@channel, exchange_name, exchange_type) do |exchange|
17
- exchange.publish(message, headers.merge(routing_key: routing_key))
19
+ def publish(exchange, type, key, message, headers = {})
20
+ with_backoff(Java::ComRabbitmqClient::AlreadyClosedException) do
21
+ debug('publishing to %s:%s with %s...' % [ type, exchange, key ])
22
+ @channel
23
+ .create_exchange(exchange, { type: type })
24
+ .publish(message, headers.merge(routing_key: key))
18
25
  end
19
26
  end
20
27
 
21
- private
22
-
23
- def open_connection(uri, options)
24
- connection =
25
- HotBunnies.connect(options.merge(
26
- host: uri.host,
27
- pass: uri.password,
28
- port: uri.port,
29
- user: uri.user,
30
- vhost: uri.path
31
- ))
32
- connection.add_shutdown_listener { |_reason| exit! }
33
- connection
34
- end
35
-
36
- def open_channel(connection)
37
- channel = connection.open_channel
38
- channel.add_shutdown_listener { |_reason| exit! }
39
- channel
40
- end
41
-
42
- def with_exchange(channel, exchange_name, exchange_type, &block)
43
- block.call(
44
- channel.exchange(exchange_name, EXCHANGE_OPTIONS.merge(
45
- type: exchange_type
46
- ))
47
- )
28
+ def disconnect
29
+ @channel.close
30
+ @connection.close
48
31
  end
49
32
  end
50
33
  end
@@ -0,0 +1,26 @@
1
+ require 'jack_rabbit/message_header'
2
+ require 'jack_rabbit/logging'
3
+
4
+ module JackRabbit
5
+ class Subscription
6
+ include Logging
7
+
8
+ DEFAULT_OPTIONS = { blocking: false }
9
+
10
+ def initialize(channel, exchange, key, queue, options, &block)
11
+ @channel = channel
12
+ @exchange, @key, @queue, @options = exchange, key, queue, options
13
+ @block = block
14
+ end
15
+
16
+ def declare
17
+ exchange = @channel.create_exchange(@exchange, @options)
18
+ queue = @channel.create_queue(@queue, @options)
19
+ queue.bind(exchange, { routing_key: @key })
20
+ @subscription =
21
+ queue.subscribe(DEFAULT_OPTIONS.merge(@options)) do |meta, message|
22
+ @block.call(MessageHeader.new(meta), message)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module JackRabbit
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: jack_rabbit
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.0
5
+ version: 0.2.0
6
6
  platform: java
7
7
  authors:
8
8
  - Sebastian Ohm
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-21 00:00:00.000000000 Z
12
+ date: 2012-12-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hot_bunnies
@@ -43,9 +43,15 @@ files:
43
43
  - dev/producer.rb
44
44
  - jack_rabbit.gemspec
45
45
  - lib/jack_rabbit.rb
46
+ - lib/jack_rabbit/backoff.rb
47
+ - lib/jack_rabbit/channel.rb
48
+ - lib/jack_rabbit/client.rb
49
+ - lib/jack_rabbit/connection.rb
46
50
  - lib/jack_rabbit/consumer.rb
51
+ - lib/jack_rabbit/logging.rb
47
52
  - lib/jack_rabbit/message_header.rb
48
53
  - lib/jack_rabbit/producer.rb
54
+ - lib/jack_rabbit/subscription.rb
49
55
  - lib/jack_rabbit/version.rb
50
56
  homepage:
51
57
  licenses: []