freddy-jruby 0.6.0 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bcd002e379a1f9326e97c95617e8027065403fcc
4
- data.tar.gz: 2982e7fae24ee6ba8e763be8426d86806406e2da
3
+ metadata.gz: 4d8614a6a2bc844445d26bf035b0ecdbd5c2e12d
4
+ data.tar.gz: c64f8114a61bd258bef376c4927110b338041d44
5
5
  SHA512:
6
- metadata.gz: d4f642d80cbb81bd9150c1cac643d4a919b18ada01cc40ad42e3c26cbc394d1f3491ac11a529243da39aeec7c1e4cc5c3d66699178ed4dc29cf6fdf4b36788be
7
- data.tar.gz: d02a32438c611aea42a2d242b7d59d1abfa73fb42a7ac1f17ebb3542059eccffb341b6bc078a822900f9112ee30d6e9615a41d52322fdf88478b7e91681bf113
6
+ metadata.gz: 648e9031be023cab9fdce260b27925331444c8ca35d4dd8321d06df494f3f0f5730f0df68b54e1f9fcf667691ef311c669260da35b99bab2f9d408aa885bba67
7
+ data.tar.gz: a1d06a5f8361ea94c18b698a035bf643bc9858b4541de331bad0a670b2f17051c458bb1383d877c8afbcabe2a78c9f0502c9d279a7dc7b080c7113268c816d68
data/Gemfile CHANGED
@@ -3,5 +3,6 @@ source 'https://rubygems.org'
3
3
  gem 'rspec'
4
4
  gem 'pry'
5
5
  gem 'codeclimate-test-reporter'
6
+ gem 'hamster', '~> 3.0'
6
7
 
7
8
  gemspec
data/README.md CHANGED
@@ -138,10 +138,7 @@ responder_handler.shutdown
138
138
 
139
139
  ## Notes about concurrency
140
140
 
141
- The underlying bunny implementation uses 1 responder thread by default. This means that if there is a time-consuming process or a sleep call in a responder then other responders will not receive messages concurrently.
142
- To resolve this problem *freddy* uses a thread pool for running concurrent responders.
143
- The thread pool is shared between *tap_into* and *respond_to* callbacks and the default size is 4.
144
- The thread pool size can be configured by passing the configuration option *max_concurrency*.
141
+ *freddy* uses a thread pool to run concurrent responders. The thread pool is unique for each *tap_into* and *respond_to* responder. Thread pool size can be configured by passing the configuration option *max_concurrency*. Its default value is 4. e.g. If your application has 2 *respond_to* responders and 1 *tap_into* responder with *max_concurrency* set to 3 then your application may process up to 9 messages in parallel.
145
142
 
146
143
 
147
144
  Note that while it is possible to use *deliver_with_response* inside a *respond_to* block,
data/freddy.gemspec CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  else
9
9
  spec.name = "freddy"
10
10
  end
11
- spec.version = '0.6.0'
12
- spec.authors = ["Urmas Talimaa"]
13
- spec.email = ["urmas.talimaa@gmail.com"]
11
+ spec.version = '0.7.2'
12
+ spec.authors = ["Salemove TechMovers"]
13
+ spec.email = ["techmovers@salemove.com"]
14
14
  spec.description = %q{Messaging API}
15
15
  spec.summary = %q{API for inter-application messaging supporting acknowledgements and request-response}
16
16
  spec.license = "Private"
@@ -27,10 +27,9 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency 'march_hare', '~> 2.12.0'
28
28
  spec.add_dependency 'symbolizer'
29
29
  else
30
- spec.add_dependency "bunny", "~> 2.5.0"
30
+ spec.add_dependency "bunny", "~> 2.6"
31
31
  spec.add_dependency "oj", "~> 2.13"
32
32
  end
33
33
 
34
- spec.add_dependency "hamster", "~> 1.0.1.pre.rc3"
35
- spec.add_dependency "thread", "~> 0.2"
34
+ spec.add_dependency "thread", "~> 0.1"
36
35
  end
data/lib/freddy.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'json'
2
2
  require 'thread/pool'
3
- require 'hamster/mutable_hash'
3
+ require 'securerandom'
4
4
 
5
5
  Dir[File.dirname(__FILE__) + '/freddy/*.rb'].each(&method(:require))
6
6
 
@@ -18,6 +18,7 @@ class Freddy
18
18
  # @option config [Integer] :port (5672)
19
19
  # @option config [String] :user ('guest')
20
20
  # @option config [String] :pass ('guest')
21
+ # @option config [Integer] :max_concurrency (4)
21
22
  #
22
23
  # @return [Freddy]
23
24
  #
@@ -25,17 +26,14 @@ class Freddy
25
26
  # Freddy.build(Logger.new(STDOUT), user: 'thumper', pass: 'howdy')
26
27
  def self.build(logger = Logger.new(STDOUT), max_concurrency: DEFAULT_MAX_CONCURRENCY, **config)
27
28
  connection = Adapters.determine.connect(config)
28
- consume_thread_pool = Thread.pool(max_concurrency)
29
29
 
30
- new(connection, logger, consume_thread_pool)
30
+ new(connection, logger, max_concurrency)
31
31
  end
32
32
 
33
- def initialize(connection, logger, consume_thread_pool)
33
+ def initialize(connection, logger, max_concurrency)
34
34
  @connection = connection
35
35
  @logger = logger
36
-
37
- @tap_into_consumer = Consumers::TapIntoConsumer.new(consume_thread_pool, @logger)
38
- @respond_to_consumer = Consumers::RespondToConsumer.new(consume_thread_pool, @logger)
36
+ @prefetch_buffer_size = max_concurrency
39
37
 
40
38
  @send_and_forget_producer = Producers::SendAndForgetProducer.new(
41
39
  connection.create_channel, logger
@@ -73,12 +71,17 @@ class Freddy
73
71
  def respond_to(destination, &callback)
74
72
  @logger.info "Listening for requests on #{destination}"
75
73
 
76
- channel = @connection.create_channel
74
+ channel = @connection.create_channel(prefetch: @prefetch_buffer_size)
77
75
  producer = Producers::ReplyProducer.new(channel, @logger)
78
76
  handler_adapter_factory = MessageHandlerAdapters::Factory.new(producer)
79
77
 
80
- @respond_to_consumer.consume(
81
- destination, channel, handler_adapter_factory, &callback
78
+ Consumers::RespondToConsumer.consume(
79
+ logger: @logger,
80
+ thread_pool: Thread.pool(@prefetch_buffer_size),
81
+ destination: destination,
82
+ channel: channel,
83
+ handler_adapter_factory: handler_adapter_factory,
84
+ &callback
82
85
  )
83
86
  end
84
87
 
@@ -91,6 +94,10 @@ class Freddy
91
94
  # @param [String] pattern
92
95
  # the destination pattern. Use `#` wildcard for matching 0 or more words.
93
96
  # Use `*` to match exactly one word.
97
+ # @param [Hash] options
98
+ # @option options [String] :group
99
+ # only one of the listeners in given group will receive a message. All
100
+ # listeners will receive a message if the group is not specified.
94
101
  #
95
102
  # @yield [message] Yields received message to the block
96
103
  #
@@ -100,9 +107,17 @@ class Freddy
100
107
  # freddy.tap_into 'notifications.*' do |message|
101
108
  # puts "Notification showed #{message.inspect}"
102
109
  # end
103
- def tap_into(pattern, &callback)
110
+ def tap_into(pattern, options = {}, &callback)
104
111
  @logger.debug "Tapping into messages that match #{pattern}"
105
- @tap_into_consumer.consume(pattern, @connection.create_channel, &callback)
112
+
113
+ Consumers::TapIntoConsumer.consume(
114
+ logger: @logger,
115
+ thread_pool: Thread.pool(@prefetch_buffer_size),
116
+ pattern: pattern,
117
+ channel: @connection.create_channel(prefetch: @prefetch_buffer_size),
118
+ options: options,
119
+ &callback
120
+ )
106
121
  end
107
122
 
108
123
  # Sends a message to given destination
@@ -24,6 +24,10 @@ class Freddy
24
24
  def name
25
25
  @queue.name
26
26
  end
27
+
28
+ def message_count
29
+ @queue.message_count
30
+ end
27
31
  end
28
32
  end
29
33
  end
@@ -13,8 +13,10 @@ class Freddy
13
13
  @bunny = bunny
14
14
  end
15
15
 
16
- def create_channel
17
- Channel.new(@bunny.create_channel)
16
+ def create_channel(prefetch: nil)
17
+ bunny_channel = @bunny.create_channel
18
+ bunny_channel.prefetch(prefetch) if prefetch
19
+ Channel.new(bunny_channel)
18
20
  end
19
21
 
20
22
  def close
@@ -30,7 +32,7 @@ class Freddy
30
32
  @channel = channel
31
33
  end
32
34
 
33
- def_delegators :@channel, :topic, :default_exchange, :consumers
35
+ def_delegators :@channel, :topic, :default_exchange, :consumers, :acknowledge
34
36
 
35
37
  def queue(*args)
36
38
  Queue.new(@channel.queue(*args))
@@ -46,10 +48,13 @@ class Freddy
46
48
  end
47
49
 
48
50
  class Queue < Shared::Queue
49
- def subscribe(&block)
50
- @queue.subscribe do |info, properties, payload|
51
+ def subscribe(manual_ack: false, &block)
52
+ @queue.subscribe(manual_ack: manual_ack) do |info, properties, payload|
51
53
  parsed_payload = Payload.parse(payload)
52
- block.call(Delivery.new(parsed_payload, properties, info.routing_key))
54
+ delivery = Delivery.new(
55
+ parsed_payload, properties, info.routing_key, info.delivery_tag
56
+ )
57
+ block.call(delivery)
53
58
  end
54
59
  end
55
60
  end
@@ -12,8 +12,10 @@ class Freddy
12
12
  @hare = hare
13
13
  end
14
14
 
15
- def create_channel
16
- Channel.new(@hare.create_channel)
15
+ def create_channel(prefetch: nil)
16
+ hare_channel = @hare.create_channel
17
+ hare_channel.basic_qos(prefetch) if prefetch
18
+ Channel.new(hare_channel)
17
19
  end
18
20
 
19
21
  def close
@@ -29,7 +31,7 @@ class Freddy
29
31
  @channel = channel
30
32
  end
31
33
 
32
- def_delegators :@channel, :topic, :default_exchange, :consumers
34
+ def_delegators :@channel, :topic, :default_exchange, :consumers, :acknowledge
33
35
 
34
36
  def queue(*args)
35
37
  Queue.new(@channel.queue(*args))
@@ -45,10 +47,13 @@ class Freddy
45
47
  end
46
48
 
47
49
  class Queue < Shared::Queue
48
- def subscribe(&block)
49
- @queue.subscribe do |meta, payload|
50
+ def subscribe(manual_ack: false, &block)
51
+ @queue.subscribe(manual_ack: manual_ack) do |meta, payload|
50
52
  parsed_payload = Payload.parse(payload)
51
- block.call(Delivery.new(parsed_payload, meta, meta.routing_key))
53
+ delivery = Delivery.new(
54
+ parsed_payload, meta, meta.routing_key, meta.delivery_tag
55
+ )
56
+ block.call(delivery)
52
57
  end
53
58
  end
54
59
  end
@@ -1,16 +1,23 @@
1
1
  class Freddy
2
2
  module Consumers
3
3
  class RespondToConsumer
4
- def initialize(consume_thread_pool, logger)
5
- @consume_thread_pool = consume_thread_pool
4
+ def self.consume(*attrs, &block)
5
+ new(*attrs).consume(&block)
6
+ end
7
+
8
+ def initialize(logger:, thread_pool:, destination:, channel:, handler_adapter_factory:)
6
9
  @logger = logger
10
+ @consume_thread_pool = thread_pool
11
+ @destination = destination
12
+ @channel = channel
13
+ @handler_adapter_factory = handler_adapter_factory
7
14
  end
8
15
 
9
- def consume(destination, channel, handler_adapter_factory, &block)
10
- consumer = consume_from_destination(destination, channel) do |delivery|
11
- Consumers.log_receive_event(@logger, destination, delivery)
16
+ def consume(&block)
17
+ consumer = consume_from_destination do |delivery|
18
+ Consumers.log_receive_event(@logger, @destination, delivery)
12
19
 
13
- adapter = handler_adapter_factory.for(delivery)
20
+ adapter = @handler_adapter_factory.for(delivery)
14
21
 
15
22
  msg_handler = MessageHandler.new(adapter, delivery)
16
23
  block.call(delivery.payload, msg_handler)
@@ -21,15 +28,19 @@ class Freddy
21
28
 
22
29
  private
23
30
 
24
- def consume_from_destination(destination, channel, &block)
25
- channel.queue(destination).subscribe do |delivery|
31
+ def consume_from_destination(&block)
32
+ @channel.queue(@destination).subscribe(manual_ack: true) do |delivery|
26
33
  process_message(delivery, &block)
27
34
  end
28
35
  end
29
36
 
30
37
  def process_message(delivery, &block)
31
38
  @consume_thread_pool.process do
32
- block.call(delivery)
39
+ begin
40
+ block.call(delivery)
41
+ ensure
42
+ @channel.acknowledge(delivery.tag, false)
43
+ end
33
44
  end
34
45
  end
35
46
  end
@@ -3,24 +3,20 @@ class Freddy
3
3
  class ResponseConsumer
4
4
  def initialize(logger)
5
5
  @logger = logger
6
- @dedicated_thread_pool = Thread.pool(1)
7
6
  end
8
7
 
9
- def consume(queue, &block)
8
+ def consume(channel, queue, &block)
10
9
  @logger.debug "Consuming messages on #{queue.name}"
11
- consumer = queue.subscribe do |delivery|
12
- process_message(queue, delivery, &block)
10
+ queue.subscribe do |delivery|
11
+ process_message(channel, queue, delivery, &block)
13
12
  end
14
- ResponderHandler.new(consumer, @dedicated_thread_pool)
15
13
  end
16
14
 
17
15
  private
18
16
 
19
- def process_message(queue, delivery, &block)
20
- @dedicated_thread_pool.process do
21
- Consumers.log_receive_event(@logger, queue.name, delivery)
22
- block.call(delivery)
23
- end
17
+ def process_message(channel, queue, delivery, &block)
18
+ Consumers.log_receive_event(@logger, queue.name, delivery)
19
+ block.call(delivery)
24
20
  end
25
21
  end
26
22
  end
@@ -1,15 +1,22 @@
1
1
  class Freddy
2
2
  module Consumers
3
3
  class TapIntoConsumer
4
- def initialize(consume_thread_pool, logger)
4
+ def self.consume(*attrs, &block)
5
+ new(*attrs).consume(&block)
6
+ end
7
+
8
+ def initialize(logger:, thread_pool:, pattern:, channel:, options:)
5
9
  @logger = logger
6
- @consume_thread_pool = consume_thread_pool
10
+ @consume_thread_pool = thread_pool
11
+ @pattern = pattern
12
+ @channel = channel
13
+ @options = options
7
14
  end
8
15
 
9
- def consume(pattern, channel, &block)
10
- queue = create_queue(pattern, channel)
16
+ def consume(&block)
17
+ queue = create_queue
11
18
 
12
- consumer = queue.subscribe do |delivery|
19
+ consumer = queue.subscribe(manual_ack: true) do |delivery|
13
20
  process_message(queue, delivery, &block)
14
21
  end
15
22
 
@@ -18,18 +25,29 @@ class Freddy
18
25
 
19
26
  private
20
27
 
21
- def create_queue(pattern, channel)
22
- topic_exchange = channel.topic(Freddy::FREDDY_TOPIC_EXCHANGE_NAME)
28
+ def create_queue
29
+ topic_exchange = @channel.topic(Freddy::FREDDY_TOPIC_EXCHANGE_NAME)
30
+ group = @options.fetch(:group, nil)
23
31
 
24
- channel
25
- .queue('', exclusive: true)
26
- .bind(topic_exchange, routing_key: pattern)
32
+ if group
33
+ @channel
34
+ .queue("groups.#{group}")
35
+ .bind(topic_exchange, routing_key: @pattern)
36
+ else
37
+ @channel
38
+ .queue('', exclusive: true)
39
+ .bind(topic_exchange, routing_key: @pattern)
40
+ end
27
41
  end
28
42
 
29
43
  def process_message(queue, delivery, &block)
30
44
  @consume_thread_pool.process do
31
- Consumers.log_receive_event(@logger, queue.name, delivery)
32
- block.call delivery.payload, delivery.routing_key
45
+ begin
46
+ Consumers.log_receive_event(@logger, queue.name, delivery)
47
+ block.call delivery.payload, delivery.routing_key
48
+ ensure
49
+ @channel.acknowledge(delivery.tag, false)
50
+ end
33
51
  end
34
52
  end
35
53
  end
@@ -1,11 +1,12 @@
1
1
  class Freddy
2
2
  class Delivery
3
- attr_reader :routing_key, :payload
3
+ attr_reader :routing_key, :payload, :tag
4
4
 
5
- def initialize(payload, metadata, routing_key)
5
+ def initialize(payload, metadata, routing_key, tag)
6
6
  @payload = payload
7
7
  @metadata = metadata
8
8
  @routing_key = routing_key
9
+ @tag = tag
9
10
  end
10
11
 
11
12
  def correlation_id
@@ -19,7 +19,7 @@ class Freddy
19
19
  @response_queue = @channel.queue("", exclusive: true)
20
20
 
21
21
  @response_consumer = Consumers::ResponseConsumer.new(@logger)
22
- @response_consumer.consume(@response_queue, &method(:handle_response))
22
+ @response_consumer.consume(@channel, @response_queue, &method(:handle_response))
23
23
  end
24
24
 
25
25
  def produce(destination, payload, timeout_in_seconds:, delete_on_timeout:, **properties)
@@ -1,23 +1,31 @@
1
1
  class Freddy
2
2
  class RequestManager
3
3
  def initialize(logger)
4
- @requests = Hamster.mutable_hash
4
+ @requests = ConcurrentHash.new
5
5
  @logger = logger
6
6
  end
7
7
 
8
8
  def no_route(correlation_id)
9
9
  if request = @requests[correlation_id]
10
- @requests.delete correlation_id
10
+ delete(correlation_id)
11
11
  request[:callback].call({error: 'Specified queue does not exist'}, nil)
12
12
  end
13
13
  end
14
14
 
15
15
  def store(correlation_id, opts)
16
- @requests.store(correlation_id, opts)
16
+ @requests[correlation_id] = opts
17
17
  end
18
18
 
19
19
  def delete(correlation_id)
20
20
  @requests.delete(correlation_id)
21
21
  end
22
+
23
+ class ConcurrentHash < Hash
24
+ # CRuby hash does not need any locks. Only adding when using JRuby.
25
+ if RUBY_PLATFORM == 'java'
26
+ require 'jruby/synchronized'
27
+ include JRuby::Synchronized
28
+ end
29
+ end
22
30
  end
23
31
  end
@@ -1,4 +1,3 @@
1
- require 'thread'
2
1
  require 'timeout'
3
2
 
4
3
  class Freddy
@@ -1,24 +1,84 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Freddy::Consumers::RespondToConsumer do
4
- let(:consumer) { described_class.new(thread_pool, logger) }
4
+ let(:consumer) do
5
+ described_class.new(
6
+ logger: logger,
7
+ thread_pool: thread_pool,
8
+ destination: destination,
9
+ channel: channel,
10
+ handler_adapter_factory: msg_handler_adapter_factory
11
+ )
12
+ end
5
13
 
6
- let(:connection) { Freddy::Adapters.determine.connect(config) }
7
- let(:thread_pool) { Thread.pool(1) }
14
+ let(:connection) { Freddy::Adapters.determine.connect(config) }
8
15
  let(:destination) { random_destination }
9
- let(:payload) { {pay: 'load'} }
10
- let(:msg_handler) { double }
16
+ let(:payload) { {pay: 'load'} }
17
+ let(:msg_handler_adapter_factory) { double(for: msg_handler_adapter) }
18
+ let(:msg_handler_adapter) { Freddy::MessageHandlerAdapters::NoOpHandler.new }
19
+ let(:prefetch_buffer_size) { 2 }
20
+ let(:thread_pool) { Thread.pool(prefetch_buffer_size) }
11
21
 
12
22
  after do
13
23
  connection.close
14
24
  end
15
25
 
16
- it "doesn't call passed block without any messages" do
17
- consumer.consume destination, connection.create_channel, msg_handler do
18
- @message_received = true
26
+ context 'when no messages' do
27
+ let(:channel) { connection.create_channel }
28
+
29
+ it "doesn't call passed block" do
30
+ consumer.consume do
31
+ @message_received = true
32
+ end
33
+ default_sleep
34
+
35
+ expect(@message_received).to be_falsy
36
+ end
37
+ end
38
+
39
+ context 'when thread pool is full' do
40
+ let(:prefetch_buffer_size) { 1 }
41
+ let(:msg_count) { prefetch_buffer_size + 1 }
42
+ let(:channel) { connection.create_channel(prefetch: prefetch_buffer_size) }
43
+ let(:mutex) { Mutex.new }
44
+ let(:consume_lock) { ConditionVariable.new }
45
+ let(:queue) { channel.queue(destination) }
46
+
47
+ after do
48
+ # Release the final queued message before finishing the test to avoid
49
+ # bunny warnings.
50
+ process_message
19
51
  end
20
- default_sleep
21
52
 
22
- expect(@message_received).to be_falsy
53
+ it 'does not consume more messages' do
54
+ consumer.consume do
55
+ wait_until_released
56
+ end
57
+
58
+ msg_count.times { deliver_message }
59
+
60
+ sleep default_sleep
61
+ expect(queue.message_count).to eq(msg_count - prefetch_buffer_size)
62
+
63
+ process_message
64
+ expect(queue.message_count).to eq(0)
65
+ end
66
+
67
+ def process_message
68
+ release_consume_lock
69
+ sleep default_sleep
70
+ end
71
+
72
+ def deliver_message
73
+ channel.default_exchange.publish('{}', routing_key: destination)
74
+ end
75
+
76
+ def wait_until_released
77
+ mutex.synchronize { consume_lock.wait(mutex) }
78
+ end
79
+
80
+ def release_consume_lock
81
+ mutex.synchronize { consume_lock.broadcast }
82
+ end
23
83
  end
24
84
  end
@@ -13,12 +13,12 @@ describe Freddy::ResponderHandler do
13
13
  count = 0
14
14
 
15
15
  consumer_handler = freddy.respond_to destination do
16
- sleep 0.1
16
+ sleep 0.3
17
17
  count += 1
18
18
  end
19
19
  deliver
20
20
 
21
- sleep 0.05
21
+ sleep 0.15
22
22
  consumer_handler.shutdown
23
23
 
24
24
  expect(count).to eq(1)
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'hamster/experimental/mutable_set'
2
3
 
3
4
  describe 'Concurrency' do
4
5
  let(:freddy1) { Freddy.build(logger, config) }
@@ -88,7 +89,7 @@ describe 'Concurrency' do
88
89
  context 'concurrent executions of deliver_with_response' do
89
90
  let(:nr_of_threads) { 50 }
90
91
  let(:payload) { {pay: 'load'} }
91
- let(:msg_counter) { Hamster.mutable_set }
92
+ let(:msg_counter) { Hamster::MutableSet[] }
92
93
  let(:queue_name) { random_destination }
93
94
 
94
95
  before do
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'hamster/experimental/mutable_set'
3
+
4
+ describe 'Tapping into with group identifier' do
5
+ let(:deliverer) { Freddy.build(logger, config) }
6
+ let(:responder1) { Freddy.build(logger, config) }
7
+ let(:responder2) { Freddy.build(logger, config) }
8
+
9
+ let(:destination) { random_destination }
10
+
11
+ after { [deliverer, responder1, responder2].each(&:close) }
12
+
13
+ it 'receives a message once' do
14
+ msg_counter = Hamster::MutableSet[]
15
+
16
+ group_id = arbitrary_id
17
+ responder1.tap_into(destination, group: group_id) {|msg| msg_counter << 'r1' }
18
+ responder2.tap_into(destination, group: group_id) {|msg| msg_counter << 'r2' }
19
+ deliverer.deliver(destination, {})
20
+
21
+ default_sleep
22
+ expect(msg_counter.count).to eq(1)
23
+ end
24
+ end
data/spec/spec_helper.rb CHANGED
@@ -12,7 +12,6 @@ SimpleCov.start do
12
12
  end
13
13
 
14
14
  require 'pry'
15
- require 'securerandom'
16
15
  require 'freddy'
17
16
  require 'logger'
18
17
  require 'hamster/experimental/mutable_set'
@@ -29,6 +28,10 @@ def random_destination
29
28
  SecureRandom.hex
30
29
  end
31
30
 
31
+ def arbitrary_id
32
+ SecureRandom.hex
33
+ end
34
+
32
35
  def default_sleep
33
36
  sleep 0.05
34
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freddy-jruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.2
5
5
  platform: ruby
6
6
  authors:
7
- - Urmas Talimaa
7
+ - Salemove TechMovers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-01 00:00:00.000000000 Z
11
+ date: 2017-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
@@ -71,21 +71,7 @@ dependencies:
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 1.0.1.pre.rc3
75
- name: hamster
76
- prerelease: false
77
- type: :runtime
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 1.0.1.pre.rc3
83
- - !ruby/object:Gem::Dependency
84
- requirement: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '0.2'
74
+ version: '0.1'
89
75
  name: thread
90
76
  prerelease: false
91
77
  type: :runtime
@@ -93,10 +79,10 @@ dependencies:
93
79
  requirements:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: '0.2'
82
+ version: '0.1'
97
83
  description: Messaging API
98
84
  email:
99
- - urmas.talimaa@gmail.com
85
+ - techmovers@salemove.com
100
86
  executables: []
101
87
  extensions: []
102
88
  extra_rdoc_files: []
@@ -143,6 +129,7 @@ files:
143
129
  - spec/integration/concurrency_spec.rb
144
130
  - spec/integration/logging_spec.rb
145
131
  - spec/integration/reply_spec.rb
132
+ - spec/integration/tap_into_with_group_spec.rb
146
133
  - spec/spec_helper.rb
147
134
  homepage:
148
135
  licenses:
@@ -164,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
151
  version: '0'
165
152
  requirements: []
166
153
  rubyforge_project:
167
- rubygems_version: 2.4.8
154
+ rubygems_version: 2.6.8
168
155
  signing_key:
169
156
  specification_version: 4
170
157
  summary: API for inter-application messaging supporting acknowledgements and request-response
@@ -178,4 +165,5 @@ test_files:
178
165
  - spec/integration/concurrency_spec.rb
179
166
  - spec/integration/logging_spec.rb
180
167
  - spec/integration/reply_spec.rb
168
+ - spec/integration/tap_into_with_group_spec.rb
181
169
  - spec/spec_helper.rb